diff options
| author | Kristian Høgsberg <krh@redhat.com> | 2007-05-09 19:23:07 -0400 |
|---|---|---|
| committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2007-05-10 12:24:14 -0400 |
| commit | ad85274fb7f1b3c8c03f6f516dc6196a19ea4296 (patch) | |
| tree | 16d0853c3f895384320504e6d3e2526a0f46508d /drivers | |
| parent | 1e4c7b0dabb46eb3a2a15cf5efbd3945b13373a0 (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')
| -rw-r--r-- | drivers/firewire/fw-sbp2.c | 134 |
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 | ||
| 522 | static int add_scsi_devices(struct fw_unit *unit); | ||
| 523 | static void remove_scsi_devices(struct fw_unit *unit); | ||
| 524 | static void sbp2_reconnect(struct work_struct *work); | 521 | static void sbp2_reconnect(struct work_struct *work); |
| 522 | static struct scsi_host_template scsi_driver_template; | ||
| 525 | 523 | ||
| 526 | static void | 524 | static void |
| 527 | release_sbp2_device(struct kref *kref) | 525 | release_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 | ||
| 542 | static void sbp2_login(struct work_struct *work) | 541 | static 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 | ||
| 700 | static int sbp2_remove(struct device *dev) | 713 | static int sbp2_remove(struct device *dev) |
| @@ -881,10 +894,10 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) | |||
| 881 | 894 | ||
| 882 | static void sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) | 895 | static 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 | ||
| 951 | static void sbp2_command_orb_map_buffer(struct sbp2_command_orb *orb) | 964 | static 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 | ||
| 976 | static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) | 989 | static 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 | ||
| 1068 | static int sbp2_scsi_slave_alloc(struct scsi_device *sdev) | 1082 | static 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 | ||
| 1080 | static int sbp2_scsi_slave_configure(struct scsi_device *sdev) | 1093 | static 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 | */ |
| 1104 | static int sbp2_scsi_abort(struct scsi_cmnd *cmd) | 1117 | static 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 | ||
| 1130 | static 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 | |||
| 1168 | static 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 | |||
| 1179 | MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>"); | 1145 | MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>"); |
| 1180 | MODULE_DESCRIPTION("SCSI over IEEE1394"); | 1146 | MODULE_DESCRIPTION("SCSI over IEEE1394"); |
| 1181 | MODULE_LICENSE("GPL"); | 1147 | MODULE_LICENSE("GPL"); |
