Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
525f0d54
Commit
525f0d54
authored
Feb 20, 2004
by
Ben Collins
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
IEEE1394/SBP2(r1144): Convert sbp2 to do one scsi_host per unit-directory.
parent
193c0042
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
215 additions
and
362 deletions
+215
-362
drivers/ieee1394/sbp2.c
drivers/ieee1394/sbp2.c
+190
-303
drivers/ieee1394/sbp2.h
drivers/ieee1394/sbp2.h
+25
-59
No files found.
drivers/ieee1394/sbp2.c
View file @
525f0d54
...
...
@@ -231,6 +231,9 @@ static Scsi_Host_Template scsi_driver_template;
const
u8
sbp2_speedto_max_payload
[]
=
{
0x7
,
0x8
,
0x9
,
0xA
,
0xB
,
0xC
};
static
void
sbp2_remove_host
(
struct
hpsb_host
*
host
);
static
void
sbp2_host_reset
(
struct
hpsb_host
*
host
);
static
struct
hpsb_highlevel
sbp2_highlevel
=
{
.
name
=
SBP2_DEVICE_NAME
,
.
remove_host
=
sbp2_remove_host
,
...
...
@@ -403,7 +406,7 @@ static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_i
unsigned
long
flags
,
orbs
;
struct
sbp2_command_info
*
command
;
orbs
=
serialize_io
?
2
:
SBP2_MAX_C
OMMAND_ORB
S
;
orbs
=
serialize_io
?
2
:
SBP2_MAX_C
MD
S
;
spin_lock_irqsave
(
&
scsi_id
->
sbp2_command_orb_lock
,
flags
);
for
(
i
=
0
;
i
<
orbs
;
i
++
)
{
...
...
@@ -541,15 +544,17 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb(
/* Free our DMA's */
static
void
sbp2util_free_command_dma
(
struct
sbp2_command_info
*
command
)
{
struct
scsi_id_instance_data
*
scsi_id
=
(
struct
scsi_id_instance_data
*
)
command
->
Current_SCpnt
->
device
->
host
->
hostdata
[
0
];
struct
hpsb_host
*
host
;
host
=
hpsb_get_host_bykey
(
&
sbp2_highlevel
,
(
unsigned
long
)
command
->
Current_SCpnt
->
device
->
host
);
if
(
!
host
)
{
printk
(
KERN_ERR
"%s: host == NULL
\n
"
,
__FUNCTION__
);
if
(
!
scsi_id
)
{
printk
(
KERN_ERR
"%s: scsi_id == NULL
\n
"
,
__FUNCTION__
);
return
;
}
host
=
scsi_id
->
ud
->
ne
->
host
;
if
(
command
->
cmd_dma
)
{
if
(
command
->
dma_type
==
CMD_DMA_SINGLE
)
{
pci_unmap_single
(
host
->
pdev
,
command
->
cmd_dma
,
...
...
@@ -591,13 +596,14 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i
/*********************************************
* IEEE-1394 core driver stack related section
*********************************************/
static
struct
scsi_id_instance_data
*
sbp2_alloc_device
(
struct
unit_directory
*
ud
);
static
int
sbp2_probe
(
struct
device
*
dev
)
{
struct
unit_directory
*
ud
;
struct
s
bp2scsi_host_info
*
hi
;
struct
s
csi_id_instance_data
*
scsi_id
;
SBP2_DEBUG
(
__FUNCTION__
);
SBP2_DEBUG
(
"sbp2_probe"
);
ud
=
container_of
(
dev
,
struct
unit_directory
,
device
);
...
...
@@ -606,55 +612,39 @@ static int sbp2_probe(struct device *dev)
if
(
ud
->
flags
&
UNIT_DIRECTORY_HAS_LUN_DIRECTORY
)
return
-
ENODEV
;
/* This will only add it if it doesn't exist */
hi
=
sbp2_add_host
(
ud
->
ne
->
host
);
scsi_id
=
sbp2_alloc_device
(
ud
);
if
(
!
hi
)
return
-
ENODEV
;
if
(
!
scsi_id
)
return
-
ENOMEM
;
return
sbp2_start_ud
(
hi
,
ud
);
sbp2_parse_unit_directory
(
scsi_id
,
ud
);
return
sbp2_start_device
(
scsi_id
);
}
static
int
sbp2_remove
(
struct
device
*
dev
)
{
struct
scsi_id_group
*
scsi_group
;
struct
list_head
*
lh
,
*
next
;
struct
unit_directory
*
ud
;
struct
scsi_id_instance_data
*
scsi_id
;
SBP2_DEBUG
(
__FUNCTION__
);
SBP2_DEBUG
(
"sbp2_remove"
);
ud
=
container_of
(
dev
,
struct
unit_directory
,
device
);
scsi_group
=
ud
->
device
.
driver_data
;
ud
->
device
.
driver_data
=
NULL
;
list_for_each_safe
(
lh
,
next
,
&
scsi_group
->
scsi_id_list
)
{
scsi_id
=
list_entry
(
lh
,
struct
scsi_id_instance_data
,
list
);
scsi_id
=
ud
->
device
.
driver_data
;
if
(
scsi_id
!=
NULL
)
{
sbp2_logout_device
(
scsi_id
);
sbp2_remove_device
(
scsi_id
);
}
}
kfree
(
scsi_group
);
return
0
;
}
static
void
sbp2_update
(
struct
unit_directory
*
ud
)
{
struct
sbp2scsi_host_info
*
hi
;
struct
scsi_id_group
*
scsi_group
=
ud
->
device
.
driver_data
;
struct
list_head
*
lh
,
*
next
;
struct
scsi_id_instance_data
*
scsi_id
;
unsigned
long
flags
;
struct
scsi_id_instance_data
*
scsi_id
=
ud
->
device
.
driver_data
;
struct
sbp2scsi_host_info
*
hi
=
scsi_id
->
hi
;
SBP2_DEBUG
(
"sbp2_update"
);
list_for_each_safe
(
lh
,
next
,
&
scsi_group
->
scsi_id_list
)
{
scsi_id
=
list_entry
(
lh
,
struct
scsi_id_instance_data
,
list
);
hi
=
scsi_id
->
hi
;
if
(
sbp2_reconnect_device
(
scsi_id
))
{
...
...
@@ -685,131 +675,121 @@ static void sbp2_update(struct unit_directory *ud)
/* Complete any pending commands with busy (so they get
* retried) and remove them from our queue
*/
spin_lock_irqsave
(
&
hi
->
sbp2_command_lock
,
flags
);
sbp2scsi_complete_all_commands
(
scsi_id
,
DID_BUS_BUSY
);
spin_unlock_irqrestore
(
&
hi
->
sbp2_command_lock
,
flags
);
}
}
/* This functions is called by the sbp2_probe, for each new device. If the
* host_info already exists, it will return it. If not, it allocated a new
* host_info entry and a corresponding scsi_host. */
static
struct
sbp2scsi_host_info
*
sbp2_add_host
(
struct
hpsb_host
*
host
)
/* This functions is called by the sbp2_probe, for each new device. We now
* allocate one scsi host for each scsi_id (unit directory). */
static
struct
scsi_id_instance_data
*
sbp2_alloc_device
(
struct
unit_directory
*
ud
)
{
struct
sbp2scsi_host_info
*
hi
;
struct
Scsi_Host
*
scsi_host
;
struct
Scsi_Host
*
scsi_host
=
NULL
;
struct
scsi_id_instance_data
*
scsi_id
=
NULL
;
SBP2_DEBUG
(
"sbp2_a
dd_host
"
);
SBP2_DEBUG
(
"sbp2_a
lloc_device
"
);
hi
=
hpsb_get_hostinfo
(
&
sbp2_highlevel
,
host
);
if
(
hi
)
return
hi
;
scsi_id
=
kmalloc
(
sizeof
(
*
scsi_id
),
GFP_KERNEL
);
if
(
!
scsi_id
)
{
SBP2_ERR
(
"failed to create scsi_id"
);
goto
failed_alloc
;
}
memset
(
scsi_id
,
0
,
sizeof
(
*
scsi_id
));
/* Register our host with the SCSI stack. */
scsi_host
=
scsi_host_alloc
(
&
scsi_driver_template
,
0
);
if
(
!
scsi_host
)
{
SBP2_ERR
(
"failed to register scsi host"
);
return
NULL
;
scsi_id
->
ne
=
ud
->
ne
;
scsi_id
->
ud
=
ud
;
scsi_id
->
speed_code
=
IEEE1394_SPEED_100
;
scsi_id
->
max_payload_size
=
sbp2_speedto_max_payload
[
IEEE1394_SPEED_100
];
atomic_set
(
&
scsi_id
->
sbp2_login_complete
,
0
);
INIT_LIST_HEAD
(
&
scsi_id
->
sbp2_command_orb_inuse
);
INIT_LIST_HEAD
(
&
scsi_id
->
sbp2_command_orb_completed
);
INIT_LIST_HEAD
(
&
scsi_id
->
scsi_list
);
scsi_id
->
sbp2_command_orb_lock
=
SPIN_LOCK_UNLOCKED
;
scsi_id
->
sbp2_device_type_and_lun
=
SBP2_DEVICE_TYPE_LUN_UNINITIALIZED
;
ud
->
device
.
driver_data
=
scsi_id
;
hi
=
hpsb_get_hostinfo
(
&
sbp2_highlevel
,
ud
->
ne
->
host
);
if
(
!
hi
)
{
hi
=
hpsb_create_hostinfo
(
&
sbp2_highlevel
,
ud
->
ne
->
host
,
sizeof
(
*
hi
));
if
(
!
hi
)
{
SBP2_ERR
(
"failed to allocate hostinfo"
);
goto
failed_alloc
;
}
SBP2_DEBUG
(
"sbp2_alloc_device: allocated hostinfo"
);
hi
->
host
=
ud
->
ne
->
host
;
INIT_LIST_HEAD
(
&
hi
->
scsi_ids
);
/* Register our sbp2 status address space... */
hpsb_register_addrspace
(
&
sbp2_highlevel
,
host
,
&
sbp2_ops
,
hpsb_register_addrspace
(
&
sbp2_highlevel
,
ud
->
ne
->
host
,
&
sbp2_ops
,
SBP2_STATUS_FIFO_ADDRESS
,
SBP2_STATUS_FIFO_ADDRESS
+
SBP2_STATUS_FIFO_ENTRY_TO_OFFSET
(
SBP2SCSI_MAX_SCSI_IDS
+
1
));
/* Handle data movement if physical dma is not enabled/supported
* on host controller */
SBP2_STATUS_FIFO_ENTRY_TO_OFFSET
(
SBP2_MAX_UDS_PER_NODE
+
1
));
#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
hpsb_register_addrspace
(
&
sbp2_highlevel
,
host
,
&
sbp2_physdma_ops
,
0x0ULL
,
0xfffffffcULL
);
/* Handle data movement if physical dma is not
* enabled/supportedon host controller */
hpsb_register_addrspace
(
&
sbp2_highlevel
,
host
,
&
sbp2_physdma_ops
,
0x0ULL
,
0xfffffffcULL
);
#endif
}
hi
=
hpsb_create_hostinfo
(
&
sbp2_highlevel
,
host
,
sizeof
(
*
hi
));
if
(
!
hi
)
{
SBP2_ERR
(
"failed to allocate hostinfo"
);
scsi_host_put
(
hi
->
scsi_host
);
scsi_id
->
hi
=
hi
;
list_add_tail
(
&
scsi_id
->
scsi_list
,
&
hi
->
scsi_ids
);
/* Register our host with the SCSI stack. */
scsi_host
=
scsi_host_alloc
(
&
scsi_driver_template
,
0
);
if
(
!
scsi_host
)
{
SBP2_ERR
(
"failed to register scsi host"
);
goto
failed_alloc
;
}
hpsb_set_hostinfo_key
(
&
sbp2_highlevel
,
host
,
(
unsigned
long
)
scsi_host
)
;
scsi_host
->
hostdata
[
0
]
=
(
unsigned
long
)
scsi_id
;
hi
->
scsi_host
=
scsi_host
;
hi
->
host
=
host
;
hi
->
sbp2_command_lock
=
SPIN_LOCK_UNLOCKED
;
hi
->
scsi_host
->
max_id
=
SBP2SCSI_MAX_SCSI_IDS
;
if
(
!
scsi_add_host
(
scsi_host
,
&
ud
->
device
))
{
scsi_id
->
scsi_host
=
scsi_
host
;
return
scsi_id
;
}
/* XXX We need a device to pass here as the scsi-host class. Can't
* use the PCI device, since it is already bound to the ieee1394
* host. Can't use the fw-host device since it is multi-class
* enabled (scsi-host uses classdata member of the device). */
if
(
scsi_add_host
(
hi
->
scsi_host
,
NULL
))
{
SBP2_ERR
(
"failed to add scsi host"
);
scsi_host_put
(
hi
->
scsi_host
);
hpsb_destroy_hostinfo
(
&
sbp2_highlevel
,
host
);
return
NULL
;
}
scsi_host_put
(
scsi_host
);
return
hi
;
failed_alloc:
sbp2_remove_device
(
scsi_id
);
return
NULL
;
}
/*
* This function is called when a host is removed.
*/
static
void
sbp2_remove_host
(
struct
hpsb_host
*
host
)
static
void
sbp2_host_reset
(
struct
hpsb_host
*
host
)
{
struct
sbp2scsi_host_info
*
hi
;
SBP2_DEBUG
(
"sbp2_remove_host"
);
struct
scsi_id_instance_data
*
scsi_id
;
hi
=
hpsb_get_hostinfo
(
&
sbp2_highlevel
,
host
);
if
(
hi
)
{
scsi_remove_host
(
hi
->
scsi_host
);
scsi_host_put
(
hi
->
scsi_host
);
list_for_each_entry
(
scsi_id
,
&
hi
->
scsi_ids
,
scsi_list
)
scsi_block_requests
(
scsi_id
->
scsi_host
);
}
}
static
int
sbp2_start_ud
(
struct
sbp2scsi_host_info
*
hi
,
struct
unit_directory
*
ud
)
{
struct
scsi_id_instance_data
*
scsi_id
,
*
scsi_id_tmp
;
struct
scsi_id_group
*
scsi_group
;
SBP2_DEBUG
(
"sbp2_start_ud"
);
scsi_group
=
kmalloc
(
sizeof
(
*
scsi_group
),
GFP_KERNEL
);
if
(
!
scsi_group
)
{
SBP2_ERR
(
"Could not allocate memory for scsi_group"
);
return
-
ENOMEM
;
}
INIT_LIST_HEAD
(
&
scsi_group
->
scsi_id_list
);
ud
->
device
.
driver_data
=
scsi_group
;
sbp2_parse_unit_directory
(
scsi_group
,
ud
,
hi
);
/* Make sure the scsi_host is ready for this */
scsi_unblock_requests
(
hi
->
scsi_host
);
list_for_each_entry_safe
(
scsi_id
,
scsi_id_tmp
,
&
scsi_group
->
scsi_id_list
,
list
)
sbp2_start_device
(
scsi_id
);
/* Check to see if any of our devices survived the ordeal */
if
(
list_empty
(
&
scsi_group
->
scsi_id_list
))
{
kfree
(
scsi_group
);
return
-
ENODEV
;
}
return
0
;
}
static
void
sbp2_host_reset
(
struct
hpsb_host
*
host
)
static
void
sbp2_remove_host
(
struct
hpsb_host
*
host
)
{
struct
sbp2scsi_host_info
*
hi
;
SBP2_DEBUG
(
"sbp2_remove_host"
);
hi
=
hpsb_get_hostinfo
(
&
sbp2_highlevel
,
host
);
if
(
hi
)
scsi_block_requests
(
hi
->
scsi_host
);
if
(
hi
)
{
struct
scsi_id_instance_data
*
scsi_id
;
list_for_each_entry
(
scsi_id
,
&
hi
->
scsi_ids
,
scsi_list
)
{
down_write
(
&
scsi_id
->
ud
->
device
.
bus
->
subsys
.
rwsem
);
device_release_driver
(
&
scsi_id
->
ud
->
device
);
up_write
(
&
scsi_id
->
ud
->
device
.
bus
->
subsys
.
rwsem
);
}
}
}
...
...
@@ -821,7 +801,6 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
{
struct
sbp2scsi_host_info
*
hi
=
scsi_id
->
hi
;
struct
scsi_device
*
sdev
;
int
i
;
SBP2_DEBUG
(
"sbp2_start_device"
);
...
...
@@ -913,7 +892,7 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
kfree
(
scsi_id
);
list_del
(
&
scsi_id
->
list
);
list_del
(
&
scsi_id
->
scsi_
list
);
SBP2_ERR
(
"Could not allocate memory for scsi_id"
);
...
...
@@ -921,17 +900,7 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
}
SBP2_DMA_ALLOC
(
"consistent DMA region for login ORB"
);
/*
* Find an empty spot to stick our scsi id instance data.
*/
for
(
i
=
0
;
i
<
hi
->
scsi_host
->
max_id
;
i
++
)
{
if
(
!
hi
->
scsi_id
[
i
])
{
hi
->
scsi_id
[
i
]
=
scsi_id
;
scsi_id
->
id
=
i
;
SBP2_DEBUG
(
"New SBP-2 device inserted, SCSI ID = %x"
,
(
unsigned
int
)
i
);
break
;
}
}
SBP2_DEBUG
(
"New SBP-2 device inserted, SCSI ID = %x"
,
scsi_id
->
ud
->
id
);
/*
* Create our command orb pool
...
...
@@ -942,15 +911,6 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
return
-
ENOMEM
;
}
/*
* Make sure we are not out of space
*/
if
(
i
==
hi
->
scsi_host
->
max_id
)
{
SBP2_ERR
(
"No slots left for SBP-2 device"
);
sbp2_remove_device
(
scsi_id
);
return
-
EBUSY
;
}
/* Schedule a timeout here. The reason is that we may be so close
* to a bus reset, that the device is not available for logins.
* This can happen when the bus reset is caused by the host
...
...
@@ -986,15 +946,12 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
sbp2_max_speed_and_size
(
scsi_id
);
/* Add this device to the scsi layer now */
sdev
=
scsi_add_device
(
hi
->
scsi_host
,
0
,
scsi_i
d
->
id
,
0
);
sdev
=
scsi_add_device
(
scsi_id
->
scsi_host
,
0
,
scsi_id
->
u
d
->
id
,
0
);
if
(
IS_ERR
(
sdev
))
{
SBP2_ERR
(
"scsi_add_device failed"
);
return
PTR_ERR
(
sdev
);
}
sdev
->
hostdata
=
scsi_id
;
scsi_id
->
sdev
=
sdev
;
return
0
;
}
...
...
@@ -1003,22 +960,24 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
*/
static
void
sbp2_remove_device
(
struct
scsi_id_instance_data
*
scsi_id
)
{
struct
sbp2scsi_host_info
*
hi
=
scsi_id
->
hi
;
struct
sbp2scsi_host_info
*
hi
;
SBP2_DEBUG
(
"sbp2_remove_device"
);
/* Complete any pending commands with selection timeout */
sbp2scsi_complete_all_commands
(
scsi_id
,
DID_NO_CONNECT
);
if
(
!
scsi_id
)
return
;
hi
=
scsi_id
->
hi
;
/*
Remove it from the scsi layer now
*/
if
(
scsi_id
->
s
dev
)
{
scsi_remove_
device
(
scsi_id
->
sdev
);
//scsi_device_put(scsi_id->sdev
);
/*
This will remove our scsi device aswell
*/
if
(
scsi_id
->
s
csi_host
)
{
scsi_remove_
host
(
scsi_id
->
scsi_host
);
scsi_host_put
(
scsi_id
->
scsi_host
);
}
sbp2util_remove_command_orb_pool
(
scsi_id
);
hi
->
scsi_id
[
scsi_id
->
id
]
=
NULL
;
list_del
(
&
scsi_id
->
scsi_list
)
;
if
(
scsi_id
->
login_response
)
{
pci_free_consistent
(
hi
->
host
->
pdev
,
...
...
@@ -1068,9 +1027,9 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id)
SBP2_DMA_FREE
(
"single query logins data"
);
}
SBP2_DEBUG
(
"SBP-2 device removed, SCSI ID = %d"
,
scsi_id
->
id
)
;
scsi_id
->
ud
->
device
.
driver_data
=
NULL
;
list_del
(
&
scsi_id
->
list
);
SBP2_DEBUG
(
"SBP-2 device removed, SCSI ID = %d"
,
scsi_id
->
ud
->
id
);
kfree
(
scsi_id
);
}
...
...
@@ -1158,7 +1117,7 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
SBP2_DEBUG
(
"sbp2_query_logins: reserved_resp_length initialized"
);
scsi_id
->
query_logins_orb
->
status_FIFO_lo
=
SBP2_STATUS_FIFO_ADDRESS_LO
+
SBP2_STATUS_FIFO_ENTRY_TO_OFFSET
(
scsi_id
->
id
);
SBP2_STATUS_FIFO_ENTRY_TO_OFFSET
(
scsi_id
->
ud
->
id
);
scsi_id
->
query_logins_orb
->
status_FIFO_hi
=
(
ORB_SET_NODE_ID
(
hi
->
host
->
node_id
)
|
SBP2_STATUS_FIFO_ADDRESS_HI
);
SBP2_DEBUG
(
"sbp2_query_logins: status FIFO initialized"
);
...
...
@@ -1272,7 +1231,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
SBP2_DEBUG
(
"sbp2_login_device: passwd_resp_lengths initialized"
);
scsi_id
->
login_orb
->
status_FIFO_lo
=
SBP2_STATUS_FIFO_ADDRESS_LO
+
SBP2_STATUS_FIFO_ENTRY_TO_OFFSET
(
scsi_id
->
id
);
SBP2_STATUS_FIFO_ENTRY_TO_OFFSET
(
scsi_id
->
ud
->
id
);
scsi_id
->
login_orb
->
status_FIFO_hi
=
(
ORB_SET_NODE_ID
(
hi
->
host
->
node_id
)
|
SBP2_STATUS_FIFO_ADDRESS_HI
);
SBP2_DEBUG
(
"sbp2_login_device: status FIFO initialized"
);
...
...
@@ -1388,7 +1347,7 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id)
scsi_id
->
logout_orb
->
reserved5
=
0x0
;
scsi_id
->
logout_orb
->
status_FIFO_lo
=
SBP2_STATUS_FIFO_ADDRESS_LO
+
SBP2_STATUS_FIFO_ENTRY_TO_OFFSET
(
scsi_id
->
id
);
SBP2_STATUS_FIFO_ENTRY_TO_OFFSET
(
scsi_id
->
ud
->
id
);
scsi_id
->
logout_orb
->
status_FIFO_hi
=
(
ORB_SET_NODE_ID
(
hi
->
host
->
node_id
)
|
SBP2_STATUS_FIFO_ADDRESS_HI
);
...
...
@@ -1448,7 +1407,7 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
scsi_id
->
reconnect_orb
->
reserved5
=
0x0
;
scsi_id
->
reconnect_orb
->
status_FIFO_lo
=
SBP2_STATUS_FIFO_ADDRESS_LO
+
SBP2_STATUS_FIFO_ENTRY_TO_OFFSET
(
scsi_id
->
id
);
SBP2_STATUS_FIFO_ENTRY_TO_OFFSET
(
scsi_id
->
ud
->
id
);
scsi_id
->
reconnect_orb
->
status_FIFO_hi
=
(
ORB_SET_NODE_ID
(
hi
->
host
->
node_id
)
|
SBP2_STATUS_FIFO_ADDRESS_HI
);
...
...
@@ -1532,45 +1491,16 @@ static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id)
}
static
struct
scsi_id_instance_data
*
sbp2_alloc_scsi_id
(
struct
scsi_id_group
*
scsi_group
,
struct
unit_directory
*
ud
,
struct
sbp2scsi_host_info
*
hi
)
{
struct
scsi_id_instance_data
*
scsi_id
=
kmalloc
(
sizeof
(
*
scsi_id
),
GFP_KERNEL
);
if
(
!
scsi_id
)
return
NULL
;
memset
(
scsi_id
,
0
,
sizeof
(
*
scsi_id
));
scsi_id
->
ne
=
ud
->
ne
;
scsi_id
->
hi
=
hi
;
scsi_id
->
ud
=
ud
;
scsi_id
->
speed_code
=
IEEE1394_SPEED_100
;
scsi_id
->
max_payload_size
=
sbp2_speedto_max_payload
[
IEEE1394_SPEED_100
];
atomic_set
(
&
scsi_id
->
sbp2_login_complete
,
0
);
INIT_LIST_HEAD
(
&
scsi_id
->
sbp2_command_orb_inuse
);
INIT_LIST_HEAD
(
&
scsi_id
->
sbp2_command_orb_completed
);
scsi_id
->
sbp2_command_orb_lock
=
SPIN_LOCK_UNLOCKED
;
scsi_id
->
sbp2_device_type_and_lun
=
SBP2_DEVICE_TYPE_LUN_UNINITIALIZED
;
list_add_tail
(
&
scsi_id
->
list
,
&
scsi_group
->
scsi_id_list
);
return
scsi_id
;
}
/*
* This function is called to parse sbp2 device's config rom unit
* directory. Used to determine things like sbp2 management agent offset,
* and command set used (SCSI or RBC).
*/
static
void
sbp2_parse_unit_directory
(
struct
scsi_id_group
*
scsi_group
,
struct
unit_directory
*
ud
,
struct
sbp2scsi_host_info
*
hi
)
static
void
sbp2_parse_unit_directory
(
struct
scsi_id_instance_data
*
scsi_id
,
struct
unit_directory
*
ud
)
{
struct
csr1212_keyval
*
kv
;
struct
csr1212_dentry
*
dentry
;
struct
scsi_id_instance_data
*
scsi_id
;
u64
management_agent_addr
;
u32
command_set_spec_id
,
command_set
,
unit_characteristics
,
firmware_revision
,
workarounds
;
...
...
@@ -1596,19 +1526,8 @@ static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group,
SBP2_DEBUG
(
"sbp2_management_agent_addr = %x"
,
(
unsigned
int
)
management_agent_addr
);
}
else
{
/*
* Device type and lun (used for
* detemining type of sbp2 device)
*/
scsi_id
=
sbp2_alloc_scsi_id
(
scsi_group
,
ud
,
hi
);
if
(
!
scsi_id
)
{
SBP2_ERR
(
"Out of memory adding scsi_id, not all LUN's will be added"
);
break
;
}
}
else
scsi_id
->
sbp2_device_type_and_lun
=
kv
->
value
.
immediate
;
}
break
;
case
SBP2_COMMAND_SET_SPEC_ID_KEY
:
...
...
@@ -1687,24 +1606,12 @@ static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group,
}
/* If this is a logical unit directory entry, process the parent
* to get the
common
values. */
* to get the values. */
if
(
ud
->
flags
&
UNIT_DIRECTORY_LUN_DIRECTORY
)
{
struct
unit_directory
*
parent_ud
=
container_of
(
ud
->
device
.
parent
,
struct
unit_directory
,
device
);
sbp2_parse_unit_directory
(
scsi_
group
,
parent_ud
,
hi
);
sbp2_parse_unit_directory
(
scsi_
id
,
parent_ud
);
}
else
{
/* If our list is empty, add a base scsi_id (happens in a normal
* case where there is no logical_unit_number entry */
if
(
list_empty
(
&
scsi_group
->
scsi_id_list
))
{
scsi_id
=
sbp2_alloc_scsi_id
(
scsi_group
,
ud
,
hi
);
if
(
!
scsi_id
)
{
SBP2_ERR
(
"Out of memory adding scsi_id"
);
return
;
}
}
/* Update the generic fields in all the LUN's */
list_for_each_entry
(
scsi_id
,
&
scsi_group
->
scsi_id_list
,
list
)
{
scsi_id
->
sbp2_management_agent_addr
=
management_agent_addr
;
scsi_id
->
sbp2_command_set_spec_id
=
command_set_spec_id
;
scsi_id
->
sbp2_command_set
=
command_set
;
...
...
@@ -1712,7 +1619,6 @@ static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group,
scsi_id
->
sbp2_firmware_revision
=
firmware_revision
;
scsi_id
->
workarounds
=
workarounds
;
}
}
}
/*
...
...
@@ -2409,10 +2315,9 @@ static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
static
int
sbp2_handle_status_write
(
struct
hpsb_host
*
host
,
int
nodeid
,
int
destid
,
quadlet_t
*
data
,
u64
addr
,
size_t
length
,
u16
fl
)
{
struct
sbp2scsi_host_info
*
hi
=
NULL
;
struct
scsi_id_instance_data
*
scsi_id
=
NULL
;
struct
sbp2scsi_host_info
*
hi
;
struct
scsi_id_instance_data
*
scsi_id
=
NULL
,
*
scsi_id_tmp
;
u32
id
;
unsigned
long
flags
;
Scsi_Cmnd
*
SCpnt
=
NULL
;
u32
scsi_status
=
SBP2_SCSI_STATUS_GOOD
;
struct
sbp2_command_info
*
command
;
...
...
@@ -2433,18 +2338,20 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
return
(
RCODE_ADDRESS_ERROR
);
}
spin_lock_irqsave
(
&
hi
->
sbp2_command_lock
,
flags
);
/*
* Find our scsi_id structure by looking at the status fifo address written to by
* the sbp2 device.
*/
id
=
SBP2_STATUS_FIFO_OFFSET_TO_ENTRY
((
u32
)(
addr
-
SBP2_STATUS_FIFO_ADDRESS
));
scsi_id
=
hi
->
scsi_id
[
id
];
list_for_each_entry
(
scsi_id_tmp
,
&
hi
->
scsi_ids
,
scsi_list
)
{
if
(
scsi_id_tmp
->
ne
->
nodeid
==
nodeid
&&
scsi_id_tmp
->
ud
->
id
==
id
)
{
scsi_id
=
scsi_id_tmp
;
break
;
}
}
if
(
!
scsi_id
)
{
SBP2_ERR
(
"scsi_id is NULL - device is gone?"
);
spin_unlock_irqrestore
(
&
hi
->
sbp2_command_lock
,
flags
);
return
(
RCODE_ADDRESS_ERROR
);
}
...
...
@@ -2532,18 +2439,9 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
}
}
spin_unlock_irqrestore
(
&
hi
->
sbp2_command_lock
,
flags
);
if
(
SCpnt
)
{
/*
* Complete the SCSI command.
*
* Only do it after we've released the sbp2_command_lock,
* as it might otherwise deadlock with the
* io_request_lock (in sbp2scsi_queuecommand).
*/
/* Complete the SCSI command. */
SBP2_DEBUG
(
"Completing SCSI command"
);
sbp2scsi_complete_command
(
scsi_id
,
scsi_status
,
SCpnt
,
command
->
Current_done
);
...
...
@@ -2564,31 +2462,26 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
*/
static
int
sbp2scsi_queuecommand
(
Scsi_Cmnd
*
SCpnt
,
void
(
*
done
)(
Scsi_Cmnd
*
))
{
struct
s
bp2scsi_host_info
*
hi
=
NULL
;
struct
scsi_id_instance_data
*
scsi_id
=
NULL
;
unsigned
long
flags
;
struct
s
csi_id_instance_data
*
scsi_id
=
(
struct
scsi_id_instance_data
*
)
SCpnt
->
device
->
host
->
hostdata
[
0
]
;
struct
sbp2scsi_host_info
*
hi
;
SBP2_DEBUG
(
"sbp2scsi_queuecommand"
);
/*
* Pull our host info and scsi id instance data from the scsi command
* If scsi_id is null, it means there is no device in this slot,
* so we should return selection timeout.
*/
hi
=
hpsb_get_hostinfo_bykey
(
&
sbp2_highlevel
,
(
unsigned
long
)
SCpnt
->
device
->
host
);
if
(
!
hi
)
{
SBP2_ERR
(
"sbp2scsi_host_info is NULL - this is bad!"
);
if
(
!
scsi_id
)
{
SCpnt
->
result
=
DID_NO_CONNECT
<<
16
;
done
(
SCpnt
);
return
(
0
)
;
return
0
;
}
scsi_id
=
hi
->
scsi_id
[
SCpnt
->
device
->
id
]
;
hi
=
scsi_id
->
hi
;
/*
* If scsi_id is null, it means there is no device in this slot,
* so we should return selection timeout.
*/
if
(
!
scsi_id
)
{
if
(
!
hi
)
{
SBP2_ERR
(
"sbp2scsi_host_info is NULL - this is bad!"
);
SCpnt
->
result
=
DID_NO_CONNECT
<<
16
;
done
(
SCpnt
);
return
(
0
);
...
...
@@ -2629,13 +2522,11 @@ static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
/*
* Try and send our SCSI command
*/
spin_lock_irqsave
(
&
hi
->
sbp2_command_lock
,
flags
);
if
(
sbp2_send_command
(
scsi_id
,
SCpnt
,
done
))
{
SBP2_ERR
(
"Error sending SCSI command"
);
sbp2scsi_complete_command
(
scsi_id
,
SBP2_SCSI_STATUS_SELECTION_TIMEOUT
,
SCpnt
,
done
);
}
spin_unlock_irqrestore
(
&
hi
->
sbp2_command_lock
,
flags
);
return
(
0
);
}
...
...
@@ -2651,7 +2542,7 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id
struct
list_head
*
lh
;
struct
sbp2_command_info
*
command
;
SBP2_DEBUG
(
"sbp2_complete_all_commands"
);
SBP2_DEBUG
(
"sbp2
scsi
_complete_all_commands"
);
while
(
!
list_empty
(
&
scsi_id
->
sbp2_command_orb_inuse
))
{
SBP2_DEBUG
(
"Found pending command to complete"
);
...
...
@@ -2671,7 +2562,7 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id
}
}
scsi_unblock_requests
(
hi
->
scsi_host
);
scsi_unblock_requests
(
scsi_id
->
scsi_host
);
return
;
}
...
...
@@ -2785,9 +2676,9 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
/*
* Tell scsi stack that we're done with this command
*/
spin_lock_irqsave
(
scsi_id
->
hi
->
scsi_host
->
host_lock
,
flags
);
spin_lock_irqsave
(
scsi_id
->
scsi_host
->
host_lock
,
flags
);
done
(
SCpnt
);
spin_unlock_irqrestore
(
scsi_id
->
hi
->
scsi_host
->
host_lock
,
flags
);
spin_unlock_irqrestore
(
scsi_id
->
scsi_host
->
host_lock
,
flags
);
return
;
}
...
...
@@ -2798,11 +2689,10 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
*/
static
int
sbp2scsi_abort
(
Scsi_Cmnd
*
SCpnt
)
{
struct
s
bp2scsi_host_info
*
hi
=
hpsb_get_hostinfo_bykey
(
&
sbp2_highlevel
,
(
unsigned
long
)
SCpnt
->
device
->
host
)
;
struct
s
csi_id_instance_data
*
scsi_id
=
hi
->
scsi_id
[
SCpnt
->
device
->
id
]
;
struct
s
csi_id_instance_data
*
scsi_id
=
(
struct
scsi_id_instance_data
*
)
SCpnt
->
device
->
host
->
hostdata
[
0
]
;
struct
s
bp2scsi_host_info
*
hi
=
scsi_id
->
hi
;
struct
sbp2_command_info
*
command
;
unsigned
long
flags
;
SBP2_ERR
(
"aborting sbp2 command"
);
print_command
(
SCpnt
->
cmnd
);
...
...
@@ -2813,7 +2703,6 @@ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt)
* Right now, just return any matching command structures
* to the free pool.
*/
spin_lock_irqsave
(
&
hi
->
sbp2_command_lock
,
flags
);
command
=
sbp2util_find_command_for_SCpnt
(
scsi_id
,
SCpnt
);
if
(
command
)
{
SBP2_DEBUG
(
"Found command to abort"
);
...
...
@@ -2838,7 +2727,6 @@ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt)
*/
sbp2_agent_reset
(
scsi_id
,
0
);
sbp2scsi_complete_all_commands
(
scsi_id
,
DID_BUS_BUSY
);
spin_unlock_irqrestore
(
&
hi
->
sbp2_command_lock
,
flags
);
}
return
(
SUCCESS
);
...
...
@@ -2849,9 +2737,8 @@ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt)
*/
static
int
sbp2scsi_reset
(
Scsi_Cmnd
*
SCpnt
)
{
struct
sbp2scsi_host_info
*
hi
=
hpsb_get_hostinfo_bykey
(
&
sbp2_highlevel
,
(
unsigned
long
)
SCpnt
->
device
->
host
);
struct
scsi_id_instance_data
*
scsi_id
=
hi
->
scsi_id
[
SCpnt
->
device
->
id
];
struct
scsi_id_instance_data
*
scsi_id
=
(
struct
scsi_id_instance_data
*
)
SCpnt
->
device
->
host
->
hostdata
[
0
];
SBP2_ERR
(
"reset requested"
);
...
...
@@ -2877,7 +2764,7 @@ static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, char *buf)
if
(
!
(
sdev
=
to_scsi_device
(
dev
)))
return
0
;
if
(
!
(
scsi_id
=
sdev
->
hostdata
))
if
(
!
(
scsi_id
=
(
struct
scsi_id_instance_data
*
)
sdev
->
host
->
hostdata
[
0
]
))
return
0
;
if
(
scsi_id
->
sbp2_device_type_and_lun
==
SBP2_DEVICE_TYPE_LUN_UNINITIALIZED
)
...
...
@@ -2914,8 +2801,8 @@ static Scsi_Host_Template scsi_driver_template = {
.
this_id
=
-
1
,
.
sg_tablesize
=
SG_ALL
,
.
use_clustering
=
ENABLE_CLUSTERING
,
.
cmd_per_lun
=
SBP2_MAX_CMDS
_PER_LUN
,
.
can_queue
=
SBP2_MAX_
SCSI_QUEUE
,
.
cmd_per_lun
=
SBP2_MAX_CMDS
,
.
can_queue
=
SBP2_MAX_
CMDS
,
.
emulated
=
1
,
.
sdev_attrs
=
sbp2_sysfs_sdev_attrs
,
};
...
...
drivers/ieee1394/sbp2.h
View file @
525f0d54
...
...
@@ -195,20 +195,22 @@ struct sbp2_status_block {
* Miscellaneous SBP2 related config rom defines
*/
/*
*
The status fifo address definition below is used as a status base, with a chunk
*
separately assigned for each sbp2 device detected. For example, 0xfffe00000000ULL
*
is used for the first sbp2 device detected, 0xfffe00000020ULL for the next sbp2
*
device
, and so on.
/*
The status fifo address definition below is used as a base for each
*
node, which a chunk seperately assigned to each unit directory in the
*
node. For example, 0xfffe00000000ULL is used for the first sbp2 device
*
detected on node 0, 0xfffe00000020ULL for the next sbp2 device on node
*
0
, and so on.
*
* Note: We could use a single status fifo address for all sbp2 devices, and figure
* out which sbp2 device the status belongs to by looking at the source node id of
* the status write... but, using separate addresses for each sbp2 device allows for
* better code and the ability to support multiple luns within a single 1394 node.
* Note: We could use a single status fifo address for all sbp2 devices,
* and figure out which sbp2 device the status belongs to by looking at
* the source node id of the status write... but, using separate addresses
* for each sbp2 unit directory allows for better code and the ability to
* support multiple luns within a single 1394 node.
*
* Also note that we choose the address range below as it is a region specified for
* write posting, where the ohci controller will automatically send an ack_complete
* when the status is written by the sbp2 device... saving a split transaction. =)
* Also note that we choose the address range below as it is a region
* specified for write posting, where the ohci controller will
* automatically send an ack_complete when the status is written by the
* sbp2 device... saving a split transaction. =)
*/
#define SBP2_STATUS_FIFO_ADDRESS 0xfffe00000000ULL
#define SBP2_STATUS_FIFO_ADDRESS_HI 0xfffe
...
...
@@ -261,7 +263,7 @@ struct sbp2_status_block {
*/
#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000
#define SBP2
SCSI_MAX_SCSI_IDS 32
/* Max sbp2 device instances supported
*/
#define SBP2
_MAX_UDS_PER_NODE 16
/* Maximum scsi devices per node
*/
#define SBP2_MAX_SECTORS 255
/* Max sectors supported */
#ifndef TYPE_SDAD
...
...
@@ -304,11 +306,8 @@ static unchar sbp2scsi_direction_table[0x100] = {
DUN
,
DUN
,
DUN
,
DUN
,
DUN
,
DUN
,
DUN
,
DUN
,
DUN
,
DUN
,
DUN
,
DUN
,
DUN
,
DUN
,
DUN
,
DUN
};
/* This should be safe. If there's more than one LUN per node, we could
* saturate the tlabel's though. */
#define SBP2_MAX_CMDS_PER_LUN 8
#define SBP2_MAX_SCSI_QUEUE (SBP2_MAX_CMDS_PER_LUN * SBP2SCSI_MAX_SCSI_IDS)
#define SBP2_MAX_COMMAND_ORBS SBP2_MAX_SCSI_QUEUE
/* This should be safe */
#define SBP2_MAX_CMDS 8
/* This is the two dma types we use for cmd_dma below */
enum
cmd_dma_types
{
...
...
@@ -351,9 +350,6 @@ struct sbp2scsi_host_info;
* Information needed on a per scsi id basis (one for each sbp2 device)
*/
struct
scsi_id_instance_data
{
/* SCSI ID */
int
id
;
/*
* Various sbp2 specific structures
*/
...
...
@@ -402,7 +398,7 @@ struct scsi_id_instance_data {
struct
list_head
sbp2_command_orb_inuse
;
struct
list_head
sbp2_command_orb_completed
;
struct
list_head
list
;
struct
list_head
scsi_
list
;
/* Node entry, as retrieved from NodeMgr entries */
struct
node_entry
*
ne
;
...
...
@@ -411,42 +407,19 @@ struct scsi_id_instance_data {
/* A backlink to our host_info */
struct
sbp2scsi_host_info
*
hi
;
/*
The scsi_device associated with this scsi_id
*/
/*
SCSI related pointers
*/
struct
scsi_device
*
sdev
;
struct
Scsi_Host
*
scsi_host
;
/* Device specific workarounds/brokeness */
u32
workarounds
;
};
/* Describes a per-ud scsi_id group */
struct
scsi_id_group
{
struct
list_head
scsi_id_list
;
};
/*
* Sbp2 host data structure (one per sbp2 host)
*/
/* Sbp2 host data structure (one per IEEE1394 host) */
struct
sbp2scsi_host_info
{
struct
hpsb_host
*
host
;
/*
* Spin locks for command processing
*/
spinlock_t
sbp2_command_lock
;
/*
* This is the scsi host we register with the scsi mid level.
* We keep a reference to it here, so we can unregister it
* when the hpsb_host is removed.
*/
struct
Scsi_Host
*
scsi_host
;
/*
* SCSI ID instance data (one for each sbp2 device instance possible)
*/
struct
scsi_id_instance_data
*
scsi_id
[
SBP2SCSI_MAX_SCSI_IDS
];
struct
hpsb_host
*
host
;
/* IEEE1394 host */
struct
list_head
scsi_ids
;
/* List of scsi ids on this host */
};
/*
...
...
@@ -469,16 +442,10 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i
/*
* IEEE-1394 core driver related prototypes
*/
static
struct
sbp2scsi_host_info
*
sbp2_add_host
(
struct
hpsb_host
*
host
);
static
void
sbp2_remove_host
(
struct
hpsb_host
*
host
);
static
void
sbp2_host_reset
(
struct
hpsb_host
*
host
);
static
int
sbp2_probe
(
struct
device
*
dev
);
static
int
sbp2_remove
(
struct
device
*
dev
);
static
void
sbp2_update
(
struct
unit_directory
*
ud
);
static
int
sbp2_start_ud
(
struct
sbp2scsi_host_info
*
hi
,
struct
unit_directory
*
ud
);
static
int
sbp2_start_device
(
struct
scsi_id_instance_data
*
scsi_id
);
static
void
sbp2_remove_device
(
struct
scsi_id_instance_data
*
scsi_id
);
...
...
@@ -513,9 +480,8 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
static
unsigned
int
sbp2_status_to_sense_data
(
unchar
*
sbp2_status
,
unchar
*
sense_data
);
static
void
sbp2_check_sbp2_command
(
struct
scsi_id_instance_data
*
scsi_id
,
unchar
*
cmd
);
static
void
sbp2_check_sbp2_response
(
struct
scsi_id_instance_data
*
scsi_id
,
Scsi_Cmnd
*
SCpnt
);
static
void
sbp2_parse_unit_directory
(
struct
scsi_id_group
*
scsi_group
,
struct
unit_directory
*
ud
,
struct
sbp2scsi_host_info
*
hi
);
static
void
sbp2_parse_unit_directory
(
struct
scsi_id_instance_data
*
scsi_id
,
struct
unit_directory
*
ud
);
static
int
sbp2_set_busy_timeout
(
struct
scsi_id_instance_data
*
scsi_id
);
static
int
sbp2_max_speed_and_size
(
struct
scsi_id_instance_data
*
scsi_id
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment