aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/fw-sbp2.c
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2007-05-09 19:23:07 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2007-05-10 12:24:14 -0400
commitad85274fb7f1b3c8c03f6f516dc6196a19ea4296 (patch)
tree16d0853c3f895384320504e6d3e2526a0f46508d /drivers/firewire/fw-sbp2.c
parent1e4c7b0dabb46eb3a2a15cf5efbd3945b13373a0 (diff)
firewire: Allocate scsi_host up front and allocate the sbp2_device as hostdata.
Avoids an extra allocation and simplifies lifetime rules for the scsi_host. Signed-off-by: Kristian Hoegsberg <krh@redhat.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire/fw-sbp2.c')
-rw-r--r--drivers/firewire/fw-sbp2.c134
1 files changed, 50 insertions, 84 deletions
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index 282e4066e8c6..c6fd7d353685 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -74,7 +74,6 @@ struct sbp2_device {
74 74
75 int retries; 75 int retries;
76 struct delayed_work work; 76 struct delayed_work work;
77 struct Scsi_Host *scsi_host;
78}; 77};
79 78
80#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000 79#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000
@@ -519,30 +518,32 @@ static int sbp2_agent_reset(struct fw_unit *unit)
519 return 0; 518 return 0;
520} 519}
521 520
522static int add_scsi_devices(struct fw_unit *unit);
523static void remove_scsi_devices(struct fw_unit *unit);
524static void sbp2_reconnect(struct work_struct *work); 521static void sbp2_reconnect(struct work_struct *work);
522static struct scsi_host_template scsi_driver_template;
525 523
526static void 524static void
527release_sbp2_device(struct kref *kref) 525release_sbp2_device(struct kref *kref)
528{ 526{
529 struct sbp2_device *sd = container_of(kref, struct sbp2_device, kref); 527 struct sbp2_device *sd = container_of(kref, struct sbp2_device, kref);
528 struct Scsi_Host *host =
529 container_of((void *)sd, struct Scsi_Host, hostdata[0]);
530 530
531 sbp2_send_management_orb(sd->unit, sd->node_id, sd->generation, 531 sbp2_send_management_orb(sd->unit, sd->node_id, sd->generation,
532 SBP2_LOGOUT_REQUEST, sd->login_id, NULL); 532 SBP2_LOGOUT_REQUEST, sd->login_id, NULL);
533 533
534 remove_scsi_devices(sd->unit); 534 scsi_remove_host(host);
535
536 fw_core_remove_address_handler(&sd->address_handler); 535 fw_core_remove_address_handler(&sd->address_handler);
537 fw_notify("removed sbp2 unit %s\n", sd->unit->device.bus_id); 536 fw_notify("removed sbp2 unit %s\n", sd->unit->device.bus_id);
538 put_device(&sd->unit->device); 537 put_device(&sd->unit->device);
539 kfree(sd); 538 scsi_host_put(host);
540} 539}
541 540
542static void sbp2_login(struct work_struct *work) 541static void sbp2_login(struct work_struct *work)
543{ 542{
544 struct sbp2_device *sd = 543 struct sbp2_device *sd =
545 container_of(work, struct sbp2_device, work.work); 544 container_of(work, struct sbp2_device, work.work);
545 struct Scsi_Host *host =
546 container_of((void *)sd, struct Scsi_Host, hostdata[0]);
546 struct fw_unit *unit = sd->unit; 547 struct fw_unit *unit = sd->unit;
547 struct fw_device *device = fw_device(unit->device.parent); 548 struct fw_device *device = fw_device(unit->device.parent);
548 struct sbp2_login_response response; 549 struct sbp2_login_response response;
@@ -562,7 +563,6 @@ static void sbp2_login(struct work_struct *work)
562 } else { 563 } else {
563 fw_error("failed to login to %s\n", 564 fw_error("failed to login to %s\n",
564 unit->device.bus_id); 565 unit->device.bus_id);
565 remove_scsi_devices(unit);
566 kref_put(&sd->kref, release_sbp2_device); 566 kref_put(&sd->kref, release_sbp2_device);
567 } 567 }
568 return; 568 return;
@@ -595,7 +595,9 @@ static void sbp2_login(struct work_struct *work)
595 PREPARE_DELAYED_WORK(&sd->work, sbp2_reconnect); 595 PREPARE_DELAYED_WORK(&sd->work, sbp2_reconnect);
596 sbp2_agent_reset(unit); 596 sbp2_agent_reset(unit);
597 597
598 retval = add_scsi_devices(unit); 598 /* FIXME: Loop over luns here. */
599 lun = 0;
600 retval = scsi_add_device(host, 0, 0, lun);
599 if (retval < 0) { 601 if (retval < 0) {
600 sbp2_send_management_orb(unit, sd->node_id, sd->generation, 602 sbp2_send_management_orb(unit, sd->node_id, sd->generation,
601 SBP2_LOGOUT_REQUEST, sd->login_id, 603 SBP2_LOGOUT_REQUEST, sd->login_id,
@@ -615,13 +617,16 @@ static int sbp2_probe(struct device *dev)
615 struct fw_device *device = fw_device(unit->device.parent); 617 struct fw_device *device = fw_device(unit->device.parent);
616 struct sbp2_device *sd; 618 struct sbp2_device *sd;
617 struct fw_csr_iterator ci; 619 struct fw_csr_iterator ci;
618 int i, key, value; 620 struct Scsi_Host *host;
621 int i, key, value, err;
619 u32 model, firmware_revision; 622 u32 model, firmware_revision;
620 623
621 sd = kzalloc(sizeof *sd, GFP_KERNEL); 624 err = -ENOMEM;
622 if (sd == NULL) 625 host = scsi_host_alloc(&scsi_driver_template, sizeof(*sd));
623 return -ENOMEM; 626 if (host == NULL)
627 goto fail;
624 628
629 sd = (struct sbp2_device *) host->hostdata;
625 unit->device.driver_data = sd; 630 unit->device.driver_data = sd;
626 sd->unit = unit; 631 sd->unit = unit;
627 INIT_LIST_HEAD(&sd->orb_list); 632 INIT_LIST_HEAD(&sd->orb_list);
@@ -631,17 +636,18 @@ static int sbp2_probe(struct device *dev)
631 sd->address_handler.address_callback = sbp2_status_write; 636 sd->address_handler.address_callback = sbp2_status_write;
632 sd->address_handler.callback_data = sd; 637 sd->address_handler.callback_data = sd;
633 638
634 if (fw_core_add_address_handler(&sd->address_handler, 639 err = fw_core_add_address_handler(&sd->address_handler,
635 &fw_high_memory_region) < 0) { 640 &fw_high_memory_region);
636 kfree(sd); 641 if (err < 0)
637 return -EBUSY; 642 goto fail_host;
638 }
639 643
640 if (fw_device_enable_phys_dma(device) < 0) { 644 err = fw_device_enable_phys_dma(device);
641 fw_core_remove_address_handler(&sd->address_handler); 645 if (err < 0)
642 kfree(sd); 646 goto fail_address_handler;
643 return -EBUSY; 647
644 } 648 err = scsi_add_host(host, &unit->device);
649 if (err < 0)
650 goto fail_address_handler;
645 651
646 /* 652 /*
647 * Scan unit directory to get management agent address, 653 * Scan unit directory to get management agent address,
@@ -695,6 +701,13 @@ static int sbp2_probe(struct device *dev)
695 kref_get(&sd->kref); 701 kref_get(&sd->kref);
696 702
697 return 0; 703 return 0;
704
705 fail_address_handler:
706 fw_core_remove_address_handler(&sd->address_handler);
707 fail_host:
708 scsi_host_put(host);
709 fail:
710 return err;
698} 711}
699 712
700static int sbp2_remove(struct device *dev) 713static int sbp2_remove(struct device *dev)
@@ -881,10 +894,10 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
881 894
882static void sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) 895static void sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
883{ 896{
884 struct fw_unit *unit = 897 struct sbp2_device *sd =
885 (struct fw_unit *)orb->cmd->device->host->hostdata[0]; 898 (struct sbp2_device *)orb->cmd->device->host->hostdata;
899 struct fw_unit *unit = sd->unit;
886 struct fw_device *device = fw_device(unit->device.parent); 900 struct fw_device *device = fw_device(unit->device.parent);
887 struct sbp2_device *sd = unit->device.driver_data;
888 struct scatterlist *sg; 901 struct scatterlist *sg;
889 int sg_len, l, i, j, count; 902 int sg_len, l, i, j, count;
890 size_t size; 903 size_t size;
@@ -950,10 +963,10 @@ static void sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
950 963
951static void sbp2_command_orb_map_buffer(struct sbp2_command_orb *orb) 964static void sbp2_command_orb_map_buffer(struct sbp2_command_orb *orb)
952{ 965{
953 struct fw_unit *unit = 966 struct sbp2_device *sd =
954 (struct fw_unit *)orb->cmd->device->host->hostdata[0]; 967 (struct sbp2_device *)orb->cmd->device->host->hostdata;
968 struct fw_unit *unit = sd->unit;
955 struct fw_device *device = fw_device(unit->device.parent); 969 struct fw_device *device = fw_device(unit->device.parent);
956 struct sbp2_device *sd = unit->device.driver_data;
957 970
958 /* 971 /*
959 * As for map_scatterlist, we need to fill in the high bits of 972 * As for map_scatterlist, we need to fill in the high bits of
@@ -975,9 +988,10 @@ static void sbp2_command_orb_map_buffer(struct sbp2_command_orb *orb)
975 988
976static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) 989static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
977{ 990{
978 struct fw_unit *unit = (struct fw_unit *)cmd->device->host->hostdata[0]; 991 struct sbp2_device *sd =
992 (struct sbp2_device *)cmd->device->host->hostdata;
993 struct fw_unit *unit = sd->unit;
979 struct fw_device *device = fw_device(unit->device.parent); 994 struct fw_device *device = fw_device(unit->device.parent);
980 struct sbp2_device *sd = unit->device.driver_data;
981 struct sbp2_command_orb *orb; 995 struct sbp2_command_orb *orb;
982 996
983 /* 997 /*
@@ -1067,8 +1081,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
1067 1081
1068static int sbp2_scsi_slave_alloc(struct scsi_device *sdev) 1082static int sbp2_scsi_slave_alloc(struct scsi_device *sdev)
1069{ 1083{
1070 struct fw_unit *unit = (struct fw_unit *)sdev->host->hostdata[0]; 1084 struct sbp2_device *sd = (struct sbp2_device *)sdev->host->hostdata;
1071 struct sbp2_device *sd = unit->device.driver_data;
1072 1085
1073 sdev->allow_restart = 1; 1086 sdev->allow_restart = 1;
1074 1087
@@ -1079,8 +1092,8 @@ static int sbp2_scsi_slave_alloc(struct scsi_device *sdev)
1079 1092
1080static int sbp2_scsi_slave_configure(struct scsi_device *sdev) 1093static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
1081{ 1094{
1082 struct fw_unit *unit = (struct fw_unit *)sdev->host->hostdata[0]; 1095 struct sbp2_device *sd = (struct sbp2_device *)sdev->host->hostdata;
1083 struct sbp2_device *sd = unit->device.driver_data; 1096 struct fw_unit *unit = sd->unit;
1084 1097
1085 sdev->use_10_for_rw = 1; 1098 sdev->use_10_for_rw = 1;
1086 1099
@@ -1103,7 +1116,9 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
1103 */ 1116 */
1104static int sbp2_scsi_abort(struct scsi_cmnd *cmd) 1117static int sbp2_scsi_abort(struct scsi_cmnd *cmd)
1105{ 1118{
1106 struct fw_unit *unit = (struct fw_unit *)cmd->device->host->hostdata[0]; 1119 struct sbp2_device *sd =
1120 (struct sbp2_device *)cmd->device->host->hostdata;
1121 struct fw_unit *unit = sd->unit;
1107 1122
1108 fw_notify("sbp2_scsi_abort\n"); 1123 fw_notify("sbp2_scsi_abort\n");
1109 sbp2_agent_reset(unit); 1124 sbp2_agent_reset(unit);
@@ -1127,55 +1142,6 @@ static struct scsi_host_template scsi_driver_template = {
1127 .can_queue = 1, 1142 .can_queue = 1,
1128}; 1143};
1129 1144
1130static int add_scsi_devices(struct fw_unit *unit)
1131{
1132 struct sbp2_device *sd = unit->device.driver_data;
1133 int retval, lun;
1134
1135 if (sd->scsi_host != NULL)
1136 return 0;
1137
1138 sd->scsi_host = scsi_host_alloc(&scsi_driver_template,
1139 sizeof(unsigned long));
1140 if (sd->scsi_host == NULL) {
1141 fw_error("failed to register scsi host\n");
1142 return -1;
1143 }
1144
1145 sd->scsi_host->hostdata[0] = (unsigned long)unit;
1146 retval = scsi_add_host(sd->scsi_host, &unit->device);
1147 if (retval < 0) {
1148 fw_error("failed to add scsi host\n");
1149 scsi_host_put(sd->scsi_host);
1150 sd->scsi_host = NULL;
1151 return retval;
1152 }
1153
1154 /* FIXME: Loop over luns here. */
1155 lun = 0;
1156 retval = scsi_add_device(sd->scsi_host, 0, 0, lun);
1157 if (retval < 0) {
1158 fw_error("failed to add scsi device\n");
1159 scsi_remove_host(sd->scsi_host);
1160 scsi_host_put(sd->scsi_host);
1161 sd->scsi_host = NULL;
1162 return retval;
1163 }
1164
1165 return 0;
1166}
1167
1168static void remove_scsi_devices(struct fw_unit *unit)
1169{
1170 struct sbp2_device *sd = unit->device.driver_data;
1171
1172 if (sd->scsi_host != NULL) {
1173 scsi_remove_host(sd->scsi_host);
1174 scsi_host_put(sd->scsi_host);
1175 }
1176 sd->scsi_host = NULL;
1177}
1178
1179MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>"); 1145MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
1180MODULE_DESCRIPTION("SCSI over IEEE1394"); 1146MODULE_DESCRIPTION("SCSI over IEEE1394");
1181MODULE_LICENSE("GPL"); 1147MODULE_LICENSE("GPL");