Commit 525f0d54 authored by Ben Collins's avatar Ben Collins

IEEE1394/SBP2(r1144): Convert sbp2 to do one scsi_host per unit-directory.

parent 193c0042
...@@ -231,6 +231,9 @@ static Scsi_Host_Template scsi_driver_template; ...@@ -231,6 +231,9 @@ static Scsi_Host_Template scsi_driver_template;
const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC }; 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 = { static struct hpsb_highlevel sbp2_highlevel = {
.name = SBP2_DEVICE_NAME, .name = SBP2_DEVICE_NAME,
.remove_host = sbp2_remove_host, .remove_host = sbp2_remove_host,
...@@ -403,7 +406,7 @@ static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_i ...@@ -403,7 +406,7 @@ static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_i
unsigned long flags, orbs; unsigned long flags, orbs;
struct sbp2_command_info *command; struct sbp2_command_info *command;
orbs = serialize_io ? 2 : SBP2_MAX_COMMAND_ORBS; orbs = serialize_io ? 2 : SBP2_MAX_CMDS;
spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
for (i = 0; i < orbs; i++) { for (i = 0; i < orbs; i++) {
...@@ -541,15 +544,17 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb( ...@@ -541,15 +544,17 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb(
/* Free our DMA's */ /* Free our DMA's */
static void sbp2util_free_command_dma(struct sbp2_command_info *command) 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; struct hpsb_host *host;
host = hpsb_get_host_bykey(&sbp2_highlevel, if (!scsi_id) {
(unsigned long)command->Current_SCpnt->device->host); printk(KERN_ERR "%s: scsi_id == NULL\n", __FUNCTION__);
if (!host) {
printk(KERN_ERR "%s: host == NULL\n", __FUNCTION__);
return; return;
} }
host = scsi_id->ud->ne->host;
if (command->cmd_dma) { if (command->cmd_dma) {
if (command->dma_type == CMD_DMA_SINGLE) { if (command->dma_type == CMD_DMA_SINGLE) {
pci_unmap_single(host->pdev, command->cmd_dma, 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 ...@@ -591,13 +596,14 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i
/********************************************* /*********************************************
* IEEE-1394 core driver stack related section * 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) static int sbp2_probe(struct device *dev)
{ {
struct unit_directory *ud; struct unit_directory *ud;
struct sbp2scsi_host_info *hi; struct scsi_id_instance_data *scsi_id;
SBP2_DEBUG(__FUNCTION__); SBP2_DEBUG("sbp2_probe");
ud = container_of(dev, struct unit_directory, device); ud = container_of(dev, struct unit_directory, device);
...@@ -606,210 +612,184 @@ static int sbp2_probe(struct device *dev) ...@@ -606,210 +612,184 @@ static int sbp2_probe(struct device *dev)
if (ud->flags & UNIT_DIRECTORY_HAS_LUN_DIRECTORY) if (ud->flags & UNIT_DIRECTORY_HAS_LUN_DIRECTORY)
return -ENODEV; return -ENODEV;
/* This will only add it if it doesn't exist */ scsi_id = sbp2_alloc_device(ud);
hi = sbp2_add_host(ud->ne->host);
if (!hi) if (!scsi_id)
return -ENODEV; return -ENOMEM;
sbp2_parse_unit_directory(scsi_id, ud);
return sbp2_start_ud(hi, ud); return sbp2_start_device(scsi_id);
} }
static int sbp2_remove(struct device *dev) static int sbp2_remove(struct device *dev)
{ {
struct scsi_id_group *scsi_group;
struct list_head *lh, *next;
struct unit_directory *ud; struct unit_directory *ud;
struct scsi_id_instance_data *scsi_id; struct scsi_id_instance_data *scsi_id;
SBP2_DEBUG(__FUNCTION__); SBP2_DEBUG("sbp2_remove");
ud = container_of(dev, struct unit_directory, device); ud = container_of(dev, struct unit_directory, device);
scsi_group = ud->device.driver_data; scsi_id = 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);
if (scsi_id != NULL) { sbp2_logout_device(scsi_id);
sbp2_logout_device(scsi_id); sbp2_remove_device(scsi_id);
sbp2_remove_device(scsi_id);
}
}
kfree(scsi_group);
return 0; return 0;
} }
static void sbp2_update(struct unit_directory *ud) static void sbp2_update(struct unit_directory *ud)
{ {
struct sbp2scsi_host_info *hi; struct scsi_id_instance_data *scsi_id = ud->device.driver_data;
struct scsi_id_group *scsi_group = ud->device.driver_data; struct sbp2scsi_host_info *hi = scsi_id->hi;
struct list_head *lh, *next;
struct scsi_id_instance_data *scsi_id;
unsigned long flags;
SBP2_DEBUG("sbp2_update"); SBP2_DEBUG("sbp2_update");
list_for_each_safe (lh, next, &scsi_group->scsi_id_list) { hi = scsi_id->hi;
scsi_id = list_entry(lh, struct scsi_id_instance_data, list);
hi = scsi_id->hi;
if (sbp2_reconnect_device(scsi_id)) { if (sbp2_reconnect_device(scsi_id)) {
/* /*
* 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); 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!");
sbp2_remove_device(scsi_id); sbp2_remove_device(scsi_id);
return; return;
}
} }
}
/* Set max retries to something large on the device. */ /* Set max retries to something large on the device. */
sbp2_set_busy_timeout(scsi_id); sbp2_set_busy_timeout(scsi_id);
/* Do a SBP-2 fetch agent reset. */ /* Do a SBP-2 fetch agent reset. */
sbp2_agent_reset(scsi_id, 1); sbp2_agent_reset(scsi_id, 1);
/* Get the max speed and packet size that we can use. */
sbp2_max_speed_and_size(scsi_id);
/* Complete any pending commands with busy (so they get /* Get the max speed and packet size that we can use. */
* retried) and remove them from our queue sbp2_max_speed_and_size(scsi_id);
*/
spin_lock_irqsave(&hi->sbp2_command_lock, flags); /* Complete any pending commands with busy (so they get
sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY); * retried) and remove them from our queue
spin_unlock_irqrestore(&hi->sbp2_command_lock, flags); */
} sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY);
} }
/* This functions is called by the sbp2_probe, for each new device. If the /* This functions is called by the sbp2_probe, for each new device. We now
* host_info already exists, it will return it. If not, it allocated a new * allocate one scsi host for each scsi_id (unit directory). */
* host_info entry and a corresponding scsi_host. */ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud)
static struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host)
{ {
struct sbp2scsi_host_info *hi; 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_add_host");
hi = hpsb_get_hostinfo(&sbp2_highlevel, host); SBP2_DEBUG("sbp2_alloc_device");
if (hi)
return hi;
/* Register our host with the SCSI stack. */ scsi_id = kmalloc(sizeof(*scsi_id), GFP_KERNEL);
scsi_host = scsi_host_alloc(&scsi_driver_template, 0); if (!scsi_id) {
if (!scsi_host) { SBP2_ERR("failed to create scsi_id");
SBP2_ERR("failed to register scsi host"); goto failed_alloc;
return NULL;
} }
memset(scsi_id, 0, sizeof(*scsi_id));
/* Register our sbp2 status address space... */ scsi_id->ne = ud->ne;
hpsb_register_addrspace(&sbp2_highlevel, host, &sbp2_ops, scsi_id->ud = ud;
SBP2_STATUS_FIFO_ADDRESS, scsi_id->speed_code = IEEE1394_SPEED_100;
SBP2_STATUS_FIFO_ADDRESS + scsi_id->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100];
SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(SBP2SCSI_MAX_SCSI_IDS+1)); 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;
/* Handle data movement if physical dma is not enabled/supported ud->device.driver_data = scsi_id;
* on host controller */
#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
hpsb_register_addrspace(&sbp2_highlevel, host, &sbp2_physdma_ops, 0x0ULL, 0xfffffffcULL);
#endif
hi = hpsb_create_hostinfo(&sbp2_highlevel, host, sizeof(*hi)); hi = hpsb_get_hostinfo(&sbp2_highlevel, ud->ne->host);
if (!hi) { if (!hi) {
SBP2_ERR("failed to allocate hostinfo"); hi = hpsb_create_hostinfo(&sbp2_highlevel, ud->ne->host, sizeof(*hi));
scsi_host_put(hi->scsi_host); 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, ud->ne->host, &sbp2_ops,
SBP2_STATUS_FIFO_ADDRESS,
SBP2_STATUS_FIFO_ADDRESS +
SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(SBP2_MAX_UDS_PER_NODE+1));
#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
/* Handle data movement if physical dma is not
* enabled/supportedon host controller */
hpsb_register_addrspace(&sbp2_highlevel, host, &sbp2_physdma_ops,
0x0ULL, 0xfffffffcULL);
#endif
} }
hpsb_set_hostinfo_key(&sbp2_highlevel, host, (unsigned long)scsi_host); scsi_id->hi = hi;
hi->scsi_host = scsi_host; list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids);
hi->host = host;
hi->sbp2_command_lock = SPIN_LOCK_UNLOCKED;
hi->scsi_host->max_id = SBP2SCSI_MAX_SCSI_IDS;
/* XXX We need a device to pass here as the scsi-host class. Can't /* Register our host with the SCSI stack. */
* use the PCI device, since it is already bound to the ieee1394 scsi_host = scsi_host_alloc(&scsi_driver_template, 0);
* host. Can't use the fw-host device since it is multi-class if (!scsi_host) {
* enabled (scsi-host uses classdata member of the device). */ SBP2_ERR("failed to register scsi host");
if (scsi_add_host(hi->scsi_host, NULL)) { goto failed_alloc;
SBP2_ERR("failed to add scsi host");
scsi_host_put(hi->scsi_host);
hpsb_destroy_hostinfo(&sbp2_highlevel, host);
return NULL;
} }
return hi; scsi_host->hostdata[0] = (unsigned long)scsi_id;
if (!scsi_add_host(scsi_host, &ud->device)) {
scsi_id->scsi_host = scsi_host;
return scsi_id;
}
SBP2_ERR("failed to add scsi host");
scsi_host_put(scsi_host);
failed_alloc:
sbp2_remove_device(scsi_id);
return NULL;
} }
/* static void sbp2_host_reset(struct hpsb_host *host)
* This function is called when a host is removed.
*/
static void sbp2_remove_host(struct hpsb_host *host)
{ {
struct sbp2scsi_host_info *hi; struct sbp2scsi_host_info *hi;
struct scsi_id_instance_data *scsi_id;
SBP2_DEBUG("sbp2_remove_host");
hi = hpsb_get_hostinfo(&sbp2_highlevel, host); hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
if (hi) { if (hi) {
scsi_remove_host(hi->scsi_host); list_for_each_entry(scsi_id, &hi->scsi_ids, scsi_list)
scsi_host_put(hi->scsi_host); 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; struct sbp2scsi_host_info *hi;
SBP2_DEBUG("sbp2_remove_host");
hi = hpsb_get_hostinfo(&sbp2_highlevel, host); hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
if (hi) if (hi) {
scsi_block_requests(hi->scsi_host); 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) ...@@ -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 sbp2scsi_host_info *hi = scsi_id->hi;
struct scsi_device *sdev; struct scsi_device *sdev;
int i;
SBP2_DEBUG("sbp2_start_device"); SBP2_DEBUG("sbp2_start_device");
...@@ -913,7 +892,7 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id) ...@@ -913,7 +892,7 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
kfree(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"); 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) ...@@ -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"); SBP2_DMA_ALLOC("consistent DMA region for login ORB");
/* SBP2_DEBUG("New SBP-2 device inserted, SCSI ID = %x", scsi_id->ud->id);
* 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;
}
}
/* /*
* Create our command orb pool * Create our command orb pool
...@@ -942,15 +911,6 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id) ...@@ -942,15 +911,6 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
return -ENOMEM; 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 /* 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. * to a bus reset, that the device is not available for logins.
* This can happen when the bus reset is caused by the host * 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) ...@@ -986,15 +946,12 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
sbp2_max_speed_and_size(scsi_id); sbp2_max_speed_and_size(scsi_id);
/* Add this device to the scsi layer now */ /* Add this device to the scsi layer now */
sdev = scsi_add_device(hi->scsi_host, 0, scsi_id->id, 0); sdev = scsi_add_device(scsi_id->scsi_host, 0, scsi_id->ud->id, 0);
if (IS_ERR(sdev)) { if (IS_ERR(sdev)) {
SBP2_ERR("scsi_add_device failed"); SBP2_ERR("scsi_add_device failed");
return PTR_ERR(sdev); return PTR_ERR(sdev);
} }
sdev->hostdata = scsi_id;
scsi_id->sdev = sdev;
return 0; return 0;
} }
...@@ -1003,22 +960,24 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id) ...@@ -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) 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"); SBP2_DEBUG("sbp2_remove_device");
/* Complete any pending commands with selection timeout */ if (!scsi_id)
sbp2scsi_complete_all_commands(scsi_id, DID_NO_CONNECT); return;
hi = scsi_id->hi;
/* Remove it from the scsi layer now */ /* This will remove our scsi device aswell */
if (scsi_id->sdev) { if (scsi_id->scsi_host) {
scsi_remove_device(scsi_id->sdev); scsi_remove_host(scsi_id->scsi_host);
//scsi_device_put(scsi_id->sdev); scsi_host_put(scsi_id->scsi_host);
} }
sbp2util_remove_command_orb_pool(scsi_id); 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) { if (scsi_id->login_response) {
pci_free_consistent(hi->host->pdev, pci_free_consistent(hi->host->pdev,
...@@ -1068,9 +1027,9 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id) ...@@ -1068,9 +1027,9 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id)
SBP2_DMA_FREE("single query logins data"); 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); kfree(scsi_id);
} }
...@@ -1158,7 +1117,7 @@ static int sbp2_query_logins(struct scsi_id_instance_data *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"); SBP2_DEBUG("sbp2_query_logins: reserved_resp_length initialized");
scsi_id->query_logins_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + 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) | scsi_id->query_logins_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |
SBP2_STATUS_FIFO_ADDRESS_HI); SBP2_STATUS_FIFO_ADDRESS_HI);
SBP2_DEBUG("sbp2_query_logins: status FIFO initialized"); SBP2_DEBUG("sbp2_query_logins: status FIFO initialized");
...@@ -1272,7 +1231,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id) ...@@ -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"); SBP2_DEBUG("sbp2_login_device: passwd_resp_lengths initialized");
scsi_id->login_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + 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) | scsi_id->login_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |
SBP2_STATUS_FIFO_ADDRESS_HI); SBP2_STATUS_FIFO_ADDRESS_HI);
SBP2_DEBUG("sbp2_login_device: status FIFO initialized"); SBP2_DEBUG("sbp2_login_device: status FIFO initialized");
...@@ -1388,7 +1347,7 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id) ...@@ -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->reserved5 = 0x0;
scsi_id->logout_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + 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) | scsi_id->logout_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |
SBP2_STATUS_FIFO_ADDRESS_HI); SBP2_STATUS_FIFO_ADDRESS_HI);
...@@ -1448,7 +1407,7 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id) ...@@ -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->reserved5 = 0x0;
scsi_id->reconnect_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + 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 = scsi_id->reconnect_orb->status_FIFO_hi =
(ORB_SET_NODE_ID(hi->host->node_id) | SBP2_STATUS_FIFO_ADDRESS_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) ...@@ -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 * 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_instance_data *scsi_id,
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;
struct scsi_id_instance_data *scsi_id;
u64 management_agent_addr; u64 management_agent_addr;
u32 command_set_spec_id, command_set, unit_characteristics, u32 command_set_spec_id, command_set, unit_characteristics,
firmware_revision, workarounds; firmware_revision, workarounds;
...@@ -1596,19 +1526,8 @@ static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group, ...@@ -1596,19 +1526,8 @@ static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group,
SBP2_DEBUG("sbp2_management_agent_addr = %x", SBP2_DEBUG("sbp2_management_agent_addr = %x",
(unsigned int) management_agent_addr); (unsigned int) management_agent_addr);
} else { } 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;
}
scsi_id->sbp2_device_type_and_lun = kv->value.immediate; scsi_id->sbp2_device_type_and_lun = kv->value.immediate;
}
break; break;
case SBP2_COMMAND_SET_SPEC_ID_KEY: case SBP2_COMMAND_SET_SPEC_ID_KEY:
...@@ -1687,31 +1606,18 @@ static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group, ...@@ -1687,31 +1606,18 @@ static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group,
} }
/* If this is a logical unit directory entry, process the parent /* 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) { 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, hi); sbp2_parse_unit_directory(scsi_id, parent_ud);
} else { } else {
/* If our list is empty, add a base scsi_id (happens in a normal scsi_id->sbp2_management_agent_addr = management_agent_addr;
* case where there is no logical_unit_number entry */ scsi_id->sbp2_command_set_spec_id = command_set_spec_id;
if (list_empty(&scsi_group->scsi_id_list)) { scsi_id->sbp2_command_set = command_set;
scsi_id = sbp2_alloc_scsi_id(scsi_group, ud, hi); scsi_id->sbp2_unit_characteristics = unit_characteristics;
if (!scsi_id) { scsi_id->sbp2_firmware_revision = firmware_revision;
SBP2_ERR("Out of memory adding scsi_id"); scsi_id->workarounds = workarounds;
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;
scsi_id->sbp2_unit_characteristics = unit_characteristics;
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, ...@@ -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, static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid,
quadlet_t *data, u64 addr, size_t length, u16 fl) quadlet_t *data, u64 addr, size_t length, u16 fl)
{ {
struct sbp2scsi_host_info *hi = NULL; struct sbp2scsi_host_info *hi;
struct scsi_id_instance_data *scsi_id = NULL; struct scsi_id_instance_data *scsi_id = NULL, *scsi_id_tmp;
u32 id; u32 id;
unsigned long flags;
Scsi_Cmnd *SCpnt = NULL; Scsi_Cmnd *SCpnt = NULL;
u32 scsi_status = SBP2_SCSI_STATUS_GOOD; u32 scsi_status = SBP2_SCSI_STATUS_GOOD;
struct sbp2_command_info *command; struct sbp2_command_info *command;
...@@ -2433,18 +2338,20 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest ...@@ -2433,18 +2338,20 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
return(RCODE_ADDRESS_ERROR); 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 * Find our scsi_id structure by looking at the status fifo address written to by
* the sbp2 device. * the sbp2 device.
*/ */
id = SBP2_STATUS_FIFO_OFFSET_TO_ENTRY((u32)(addr - SBP2_STATUS_FIFO_ADDRESS)); 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) { if (!scsi_id) {
SBP2_ERR("scsi_id is NULL - device is gone?"); SBP2_ERR("scsi_id is NULL - device is gone?");
spin_unlock_irqrestore(&hi->sbp2_command_lock, flags);
return(RCODE_ADDRESS_ERROR); return(RCODE_ADDRESS_ERROR);
} }
...@@ -2532,18 +2439,9 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest ...@@ -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) { if (SCpnt) {
/* /* Complete the SCSI command. */
* 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).
*/
SBP2_DEBUG("Completing SCSI command"); SBP2_DEBUG("Completing SCSI command");
sbp2scsi_complete_command(scsi_id, scsi_status, SCpnt, sbp2scsi_complete_command(scsi_id, scsi_status, SCpnt,
command->Current_done); command->Current_done);
...@@ -2564,31 +2462,26 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest ...@@ -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 *)) static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
{ {
struct sbp2scsi_host_info *hi = NULL; struct scsi_id_instance_data *scsi_id =
struct scsi_id_instance_data *scsi_id = NULL; (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
unsigned long flags; struct sbp2scsi_host_info *hi;
SBP2_DEBUG("sbp2scsi_queuecommand"); 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 (!scsi_id) {
if (!hi) {
SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!");
SCpnt->result = DID_NO_CONNECT << 16; SCpnt->result = DID_NO_CONNECT << 16;
done (SCpnt); done (SCpnt);
return(0); return 0;
} }
scsi_id = hi->scsi_id[SCpnt->device->id]; hi = scsi_id->hi;
/* if (!hi) {
* If scsi_id is null, it means there is no device in this slot, SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!");
* so we should return selection timeout.
*/
if (!scsi_id) {
SCpnt->result = DID_NO_CONNECT << 16; SCpnt->result = DID_NO_CONNECT << 16;
done (SCpnt); done (SCpnt);
return(0); return(0);
...@@ -2629,13 +2522,11 @@ static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) ...@@ -2629,13 +2522,11 @@ static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
/* /*
* Try and send our SCSI command * Try and send our SCSI command
*/ */
spin_lock_irqsave(&hi->sbp2_command_lock, flags);
if (sbp2_send_command(scsi_id, SCpnt, done)) { if (sbp2_send_command(scsi_id, SCpnt, done)) {
SBP2_ERR("Error sending SCSI command"); SBP2_ERR("Error sending SCSI command");
sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT, sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT,
SCpnt, done); SCpnt, done);
} }
spin_unlock_irqrestore(&hi->sbp2_command_lock, flags);
return(0); return(0);
} }
...@@ -2651,7 +2542,7 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id ...@@ -2651,7 +2542,7 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id
struct list_head *lh; struct list_head *lh;
struct sbp2_command_info *command; struct sbp2_command_info *command;
SBP2_DEBUG("sbp2_complete_all_commands"); SBP2_DEBUG("sbp2scsi_complete_all_commands");
while (!list_empty(&scsi_id->sbp2_command_orb_inuse)) { while (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
SBP2_DEBUG("Found pending command to complete"); SBP2_DEBUG("Found pending command to complete");
...@@ -2671,7 +2562,7 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id ...@@ -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; return;
} }
...@@ -2785,9 +2676,9 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, ...@@ -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 * 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); done (SCpnt);
spin_unlock_irqrestore(scsi_id->hi->scsi_host->host_lock,flags); spin_unlock_irqrestore(scsi_id->scsi_host->host_lock,flags);
return; return;
} }
...@@ -2798,11 +2689,10 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, ...@@ -2798,11 +2689,10 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
*/ */
static int sbp2scsi_abort (Scsi_Cmnd *SCpnt) static int sbp2scsi_abort (Scsi_Cmnd *SCpnt)
{ {
struct sbp2scsi_host_info *hi = hpsb_get_hostinfo_bykey(&sbp2_highlevel, struct scsi_id_instance_data *scsi_id =
(unsigned long)SCpnt->device->host); (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
struct scsi_id_instance_data *scsi_id = hi->scsi_id[SCpnt->device->id]; struct sbp2scsi_host_info *hi = scsi_id->hi;
struct sbp2_command_info *command; struct sbp2_command_info *command;
unsigned long flags;
SBP2_ERR("aborting sbp2 command"); SBP2_ERR("aborting sbp2 command");
print_command (SCpnt->cmnd); print_command (SCpnt->cmnd);
...@@ -2813,7 +2703,6 @@ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt) ...@@ -2813,7 +2703,6 @@ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt)
* Right now, just return any matching command structures * Right now, just return any matching command structures
* to the free pool. * to the free pool.
*/ */
spin_lock_irqsave(&hi->sbp2_command_lock, flags);
command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt); command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt);
if (command) { if (command) {
SBP2_DEBUG("Found command to abort"); SBP2_DEBUG("Found command to abort");
...@@ -2838,7 +2727,6 @@ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt) ...@@ -2838,7 +2727,6 @@ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt)
*/ */
sbp2_agent_reset(scsi_id, 0); sbp2_agent_reset(scsi_id, 0);
sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY); sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY);
spin_unlock_irqrestore(&hi->sbp2_command_lock, flags);
} }
return(SUCCESS); return(SUCCESS);
...@@ -2849,9 +2737,8 @@ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt) ...@@ -2849,9 +2737,8 @@ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt)
*/ */
static int sbp2scsi_reset (Scsi_Cmnd *SCpnt) static int sbp2scsi_reset (Scsi_Cmnd *SCpnt)
{ {
struct sbp2scsi_host_info *hi = hpsb_get_hostinfo_bykey(&sbp2_highlevel, struct scsi_id_instance_data *scsi_id =
(unsigned long)SCpnt->device->host); (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
struct scsi_id_instance_data *scsi_id = hi->scsi_id[SCpnt->device->id];
SBP2_ERR("reset requested"); SBP2_ERR("reset requested");
...@@ -2877,7 +2764,7 @@ static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, char *buf) ...@@ -2877,7 +2764,7 @@ static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, char *buf)
if (!(sdev = to_scsi_device(dev))) if (!(sdev = to_scsi_device(dev)))
return 0; return 0;
if (!(scsi_id = sdev->hostdata)) if (!(scsi_id = (struct scsi_id_instance_data *)sdev->host->hostdata[0]))
return 0; return 0;
if (scsi_id->sbp2_device_type_and_lun == SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) if (scsi_id->sbp2_device_type_and_lun == SBP2_DEVICE_TYPE_LUN_UNINITIALIZED)
...@@ -2914,8 +2801,8 @@ static Scsi_Host_Template scsi_driver_template = { ...@@ -2914,8 +2801,8 @@ static Scsi_Host_Template scsi_driver_template = {
.this_id = -1, .this_id = -1,
.sg_tablesize = SG_ALL, .sg_tablesize = SG_ALL,
.use_clustering = ENABLE_CLUSTERING, .use_clustering = ENABLE_CLUSTERING,
.cmd_per_lun = SBP2_MAX_CMDS_PER_LUN, .cmd_per_lun = SBP2_MAX_CMDS,
.can_queue = SBP2_MAX_SCSI_QUEUE, .can_queue = SBP2_MAX_CMDS,
.emulated = 1, .emulated = 1,
.sdev_attrs = sbp2_sysfs_sdev_attrs, .sdev_attrs = sbp2_sysfs_sdev_attrs,
}; };
......
...@@ -195,20 +195,22 @@ struct sbp2_status_block { ...@@ -195,20 +195,22 @@ struct sbp2_status_block {
* Miscellaneous SBP2 related config rom defines * Miscellaneous SBP2 related config rom defines
*/ */
/* /* The status fifo address definition below is used as a base for each
* The status fifo address definition below is used as a status base, with a chunk * node, which a chunk seperately assigned to each unit directory in the
* separately assigned for each sbp2 device detected. For example, 0xfffe00000000ULL * node. For example, 0xfffe00000000ULL is used for the first sbp2 device
* is used for the first sbp2 device detected, 0xfffe00000020ULL for the next sbp2 * detected on node 0, 0xfffe00000020ULL for the next sbp2 device on node
* device, and so on. * 0, and so on.
* *
* Note: We could use a single status fifo address for all sbp2 devices, and figure * Note: We could use a single status fifo address for all sbp2 devices,
* out which sbp2 device the status belongs to by looking at the source node id of * and figure out which sbp2 device the status belongs to by looking at
* the status write... but, using separate addresses for each sbp2 device allows for * the source node id of the status write... but, using separate addresses
* better code and the ability to support multiple luns within a single 1394 node. * 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 * Also note that we choose the address range below as it is a region
* write posting, where the ohci controller will automatically send an ack_complete * specified for write posting, where the ohci controller will
* when the status is written by the sbp2 device... saving a split transaction. =) * 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 0xfffe00000000ULL
#define SBP2_STATUS_FIFO_ADDRESS_HI 0xfffe #define SBP2_STATUS_FIFO_ADDRESS_HI 0xfffe
...@@ -261,7 +263,7 @@ struct sbp2_status_block { ...@@ -261,7 +263,7 @@ struct sbp2_status_block {
*/ */
#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000 #define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000
#define SBP2SCSI_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 */ #define SBP2_MAX_SECTORS 255 /* Max sectors supported */
#ifndef TYPE_SDAD #ifndef TYPE_SDAD
...@@ -304,11 +306,8 @@ static unchar sbp2scsi_direction_table[0x100] = { ...@@ -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 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 /* This should be safe */
* saturate the tlabel's though. */ #define SBP2_MAX_CMDS 8
#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 is the two dma types we use for cmd_dma below */ /* This is the two dma types we use for cmd_dma below */
enum cmd_dma_types { enum cmd_dma_types {
...@@ -351,9 +350,6 @@ struct sbp2scsi_host_info; ...@@ -351,9 +350,6 @@ struct sbp2scsi_host_info;
* Information needed on a per scsi id basis (one for each sbp2 device) * Information needed on a per scsi id basis (one for each sbp2 device)
*/ */
struct scsi_id_instance_data { struct scsi_id_instance_data {
/* SCSI ID */
int id;
/* /*
* Various sbp2 specific structures * Various sbp2 specific structures
*/ */
...@@ -402,7 +398,7 @@ struct scsi_id_instance_data { ...@@ -402,7 +398,7 @@ struct scsi_id_instance_data {
struct list_head sbp2_command_orb_inuse; struct list_head sbp2_command_orb_inuse;
struct list_head sbp2_command_orb_completed; struct list_head sbp2_command_orb_completed;
struct list_head list; struct list_head scsi_list;
/* Node entry, as retrieved from NodeMgr entries */ /* Node entry, as retrieved from NodeMgr entries */
struct node_entry *ne; struct node_entry *ne;
...@@ -411,42 +407,19 @@ struct scsi_id_instance_data { ...@@ -411,42 +407,19 @@ struct scsi_id_instance_data {
/* A backlink to our host_info */ /* A backlink to our host_info */
struct sbp2scsi_host_info *hi; struct sbp2scsi_host_info *hi;
/* The scsi_device associated with this scsi_id */ /* SCSI related pointers */
struct scsi_device *sdev; struct scsi_device *sdev;
struct Scsi_Host *scsi_host;
/* Device specific workarounds/brokeness */ /* Device specific workarounds/brokeness */
u32 workarounds; u32 workarounds;
}; };
/* Describes a per-ud scsi_id group */ /* Sbp2 host data structure (one per IEEE1394 host) */
struct scsi_id_group {
struct list_head scsi_id_list;
};
/*
* Sbp2 host data structure (one per sbp2 host)
*/
struct sbp2scsi_host_info { struct sbp2scsi_host_info {
struct hpsb_host *host; struct hpsb_host *host; /* IEEE1394 host */
struct list_head scsi_ids; /* List of scsi ids on this 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];
}; };
/* /*
...@@ -469,16 +442,10 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i ...@@ -469,16 +442,10 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i
/* /*
* IEEE-1394 core driver related prototypes * 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_probe(struct device *dev);
static int sbp2_remove(struct device *dev); static int sbp2_remove(struct device *dev);
static void sbp2_update(struct unit_directory *ud); 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 int sbp2_start_device(struct scsi_id_instance_data *scsi_id);
static void sbp2_remove_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, ...@@ -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 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_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_instance_data *scsi_id,
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