Commit 93f136bc authored by Ben Collins's avatar Ben Collins

IEEE1394(r1128): Implement bus reset handling for hosts (based on patch from Oracle)

parent 80a89b96
...@@ -234,6 +234,7 @@ const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC }; ...@@ -234,6 +234,7 @@ const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC };
static struct hpsb_highlevel sbp2_highlevel = { static struct hpsb_highlevel sbp2_highlevel = {
.name = SBP2_DEVICE_NAME, .name = SBP2_DEVICE_NAME,
.remove_host = sbp2_remove_host, .remove_host = sbp2_remove_host,
.host_reset = sbp2_host_reset,
}; };
static struct hpsb_address_ops sbp2_ops = { static struct hpsb_address_ops sbp2_ops = {
...@@ -666,6 +667,8 @@ static void sbp2_update(struct unit_directory *ud) ...@@ -666,6 +667,8 @@ static void sbp2_update(struct unit_directory *ud)
* Ok, reconnect has failed. Perhaps we didn't * Ok, reconnect has failed. Perhaps we didn't
* reconnect fast enough. Try doing a regular login. * reconnect fast enough. Try doing a regular login.
*/ */
sbp2_logout_device(scsi_id);
if (sbp2_login_device(scsi_id)) { if (sbp2_login_device(scsi_id)) {
/* Login failed too, just remove the device. */ /* Login failed too, just remove the device. */
SBP2_ERR("sbp2_reconnect_device failed!"); SBP2_ERR("sbp2_reconnect_device failed!");
...@@ -772,9 +775,8 @@ static void sbp2_remove_host(struct hpsb_host *host) ...@@ -772,9 +775,8 @@ static void sbp2_remove_host(struct hpsb_host *host)
static int sbp2_start_ud(struct sbp2scsi_host_info *hi, struct unit_directory *ud) static int sbp2_start_ud(struct sbp2scsi_host_info *hi, struct unit_directory *ud)
{ {
struct scsi_id_instance_data *scsi_id; struct scsi_id_instance_data *scsi_id, *scsi_id_tmp;
struct scsi_id_group *scsi_group; struct scsi_id_group *scsi_group;
struct list_head *lh, *next;
SBP2_DEBUG("sbp2_start_ud"); SBP2_DEBUG("sbp2_start_ud");
...@@ -786,22 +788,13 @@ static int sbp2_start_ud(struct sbp2scsi_host_info *hi, struct unit_directory *u ...@@ -786,22 +788,13 @@ static int sbp2_start_ud(struct sbp2scsi_host_info *hi, struct unit_directory *u
INIT_LIST_HEAD(&scsi_group->scsi_id_list); INIT_LIST_HEAD(&scsi_group->scsi_id_list);
ud->device.driver_data = scsi_group; ud->device.driver_data = scsi_group;
sbp2_parse_unit_directory(scsi_group, ud); sbp2_parse_unit_directory(scsi_group, ud, hi);
list_for_each_safe (lh, next, &scsi_group->scsi_id_list) {
scsi_id = list_entry(lh, struct scsi_id_instance_data, list);
scsi_id->ne = ud->ne; /* Make sure the scsi_host is ready for this */
scsi_id->hi = hi; scsi_unblock_requests(hi->scsi_host);
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;
list_for_each_entry_safe(scsi_id, scsi_id_tmp, &scsi_group->scsi_id_list, list)
sbp2_start_device(scsi_id); sbp2_start_device(scsi_id);
}
/* Check to see if any of our devices survived the ordeal */ /* Check to see if any of our devices survived the ordeal */
if (list_empty(&scsi_group->scsi_id_list)) { if (list_empty(&scsi_group->scsi_id_list)) {
...@@ -813,6 +806,16 @@ static int sbp2_start_ud(struct sbp2scsi_host_info *hi, struct unit_directory *u ...@@ -813,6 +806,16 @@ static int sbp2_start_ud(struct sbp2scsi_host_info *hi, struct unit_directory *u
} }
static void sbp2_host_reset(struct hpsb_host *host)
{
struct sbp2scsi_host_info *hi;
hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
scsi_block_requests(hi->scsi_host);
}
/* /*
* This function is where we first pull the node unique ids, and then * This function is where we first pull the node unique ids, and then
* allocate memory and register a SBP-2 device. * allocate memory and register a SBP-2 device.
...@@ -1013,7 +1016,7 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id) ...@@ -1013,7 +1016,7 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id)
/* Remove it from the scsi layer now */ /* Remove it from the scsi layer now */
if (scsi_id->sdev) { if (scsi_id->sdev) {
scsi_remove_device(scsi_id->sdev); scsi_remove_device(scsi_id->sdev);
scsi_device_put(scsi_id->sdev); //scsi_device_put(scsi_id->sdev);
} }
sbp2util_remove_command_orb_pool(scsi_id); sbp2util_remove_command_orb_pool(scsi_id);
...@@ -1531,13 +1534,31 @@ static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id) ...@@ -1531,13 +1534,31 @@ static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id)
return(0); return(0);
} }
static void sbp2_prep_scsi_id(struct scsi_id_instance_data *scsi_id,
struct unit_directory *ud,
struct sbp2scsi_host_info *hi)
{
memset(scsi_id, 0, sizeof(*scsi_id));
scsi_id->ne = ud->ne;
scsi_id->hi = hi;
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;
}
/* /*
* This function is called to parse sbp2 device's config rom unit * This function is called to parse sbp2 device's config rom unit
* directory. Used to determine things like sbp2 management agent offset, * directory. Used to determine things like sbp2 management agent offset,
* and command set used (SCSI or RBC). * and command set used (SCSI or RBC).
*/ */
static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group, static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group,
struct unit_directory *ud) struct unit_directory *ud,
struct sbp2scsi_host_info *hi)
{ {
struct csr1212_keyval *kv; struct csr1212_keyval *kv;
struct csr1212_dentry *dentry; struct csr1212_dentry *dentry;
...@@ -1578,7 +1599,7 @@ static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group, ...@@ -1578,7 +1599,7 @@ static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group,
SBP2_ERR("Out of memory adding scsi_id, not all LUN's will be added"); SBP2_ERR("Out of memory adding scsi_id, not all LUN's will be added");
break; break;
} }
memset(scsi_id, 0, sizeof(*scsi_id)); sbp2_prep_scsi_id(scsi_id, ud, hi);
scsi_id->sbp2_device_type_and_lun = kv->value.immediate; scsi_id->sbp2_device_type_and_lun = kv->value.immediate;
SBP2_DEBUG("sbp2_device_type_and_lun = %x", SBP2_DEBUG("sbp2_device_type_and_lun = %x",
...@@ -1667,7 +1688,7 @@ static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group, ...@@ -1667,7 +1688,7 @@ static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group,
if (ud->flags & UNIT_DIRECTORY_LUN_DIRECTORY) { if (ud->flags & UNIT_DIRECTORY_LUN_DIRECTORY) {
struct unit_directory *parent_ud = struct unit_directory *parent_ud =
container_of(ud->device.parent, struct unit_directory, device); container_of(ud->device.parent, struct unit_directory, device);
sbp2_parse_unit_directory(scsi_group, parent_ud); sbp2_parse_unit_directory(scsi_group, parent_ud, hi);
} else { } else {
/* If our list is empty, add a base scsi_id (happens in a normal /* If our list is empty, add a base scsi_id (happens in a normal
* case where there is no logical_unit_number entry */ * case where there is no logical_unit_number entry */
...@@ -1677,7 +1698,8 @@ static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group, ...@@ -1677,7 +1698,8 @@ static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group,
SBP2_ERR("Out of memory adding scsi_id"); SBP2_ERR("Out of memory adding scsi_id");
return; return;
} }
memset(scsi_id, 0, sizeof(*scsi_id));
sbp2_prep_scsi_id(scsi_id, ud, hi);
scsi_id->sbp2_device_type_and_lun = SBP2_DEVICE_TYPE_LUN_UNINITIALIZED; scsi_id->sbp2_device_type_and_lun = SBP2_DEVICE_TYPE_LUN_UNINITIALIZED;
list_add_tail(&scsi_id->list, &scsi_group->scsi_id_list); list_add_tail(&scsi_id->list, &scsi_group->scsi_id_list);
...@@ -2653,6 +2675,8 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id ...@@ -2653,6 +2675,8 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id
} }
} }
scsi_unblock_requests(hi->scsi_host);
return; return;
} }
......
...@@ -470,6 +470,7 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i ...@@ -470,6 +470,7 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i
*/ */
static struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host); static struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host);
static void sbp2_remove_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_probe(struct device *dev);
static int sbp2_remove(struct device *dev); static int sbp2_remove(struct device *dev);
...@@ -512,7 +513,8 @@ static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense ...@@ -512,7 +513,8 @@ static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense
static void sbp2_check_sbp2_command(struct scsi_id_instance_data *scsi_id, unchar *cmd); 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_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, static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group,
struct unit_directory *ud); struct unit_directory *ud,
struct sbp2scsi_host_info *hi);
static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id); 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); static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment