Commit b2af07b6844aade3a6d69511625bef2b1cb609cc

Authored by Stefan Richter
1 parent 6ff8147d07

firewire: sbp2: move some code to more sensible places

Implement sbp2_queue_work(), which is now a very simple accessor to one
of the struct sbp2_logical_unit members, right after the definition of
struct sbp2_logical_unit.

Put the sbp2_reconnect() implementation right after the sbp2_login()
implementation.  They are both part of the SBP-2 access protocol.

Implement the driver methods sbp2_probe(), spp2_update(), sbp2_remove()
in this order, reflecting the lifetime of an SBP-2 target.

Place the sbp2_release_target() implementation right next to
sbp2_remove() which is its primary user, and after sbp2_probe() which is
the counterpart to sbp2_release_target().

There are no changes to the implementations here, or at least not meant
to be.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

Showing 1 changed file with 107 additions and 106 deletions Side-by-side Diff

drivers/firewire/sbp2.c
... ... @@ -154,6 +154,11 @@
154 154 bool blocked;
155 155 };
156 156  
  157 +static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
  158 +{
  159 + queue_delayed_work(fw_workqueue, &lu->work, delay);
  160 +}
  161 +
157 162 /*
158 163 * We create one struct sbp2_target per IEEE 1212 Unit Directory
159 164 * and one struct Scsi_Host per sbp2_target.
... ... @@ -771,52 +776,6 @@
771 776 return scsilun_to_int(&eight_bytes_lun);
772 777 }
773 778  
774   -static void sbp2_release_target(struct sbp2_target *tgt)
775   -{
776   - struct sbp2_logical_unit *lu, *next;
777   - struct Scsi_Host *shost =
778   - container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
779   - struct scsi_device *sdev;
780   - struct fw_device *device = target_device(tgt);
781   -
782   - /* prevent deadlocks */
783   - sbp2_unblock(tgt);
784   -
785   - list_for_each_entry_safe(lu, next, &tgt->lu_list, link) {
786   - sdev = scsi_device_lookup(shost, 0, 0, sbp2_lun2int(lu->lun));
787   - if (sdev) {
788   - scsi_remove_device(sdev);
789   - scsi_device_put(sdev);
790   - }
791   - if (lu->login_id != INVALID_LOGIN_ID) {
792   - int generation, node_id;
793   - /*
794   - * tgt->node_id may be obsolete here if we failed
795   - * during initial login or after a bus reset where
796   - * the topology changed.
797   - */
798   - generation = device->generation;
799   - smp_rmb(); /* node_id vs. generation */
800   - node_id = device->node_id;
801   - sbp2_send_management_orb(lu, node_id, generation,
802   - SBP2_LOGOUT_REQUEST,
803   - lu->login_id, NULL);
804   - }
805   - fw_core_remove_address_handler(&lu->address_handler);
806   - list_del(&lu->link);
807   - kfree(lu);
808   - }
809   - scsi_remove_host(shost);
810   - fw_notify("released %s, target %d:0:0\n", tgt->bus_id, shost->host_no);
811   -
812   - scsi_host_put(shost);
813   -}
814   -
815   -static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
816   -{
817   - queue_delayed_work(fw_workqueue, &lu->work, delay);
818   -}
819   -
820 779 /*
821 780 * Write retransmit retry values into the BUSY_TIMEOUT register.
822 781 * - The single-phase retry protocol is supported by all SBP-2 devices, but the
... ... @@ -955,6 +914,57 @@
955 914 PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
956 915 }
957 916  
  917 +static void sbp2_reconnect(struct work_struct *work)
  918 +{
  919 + struct sbp2_logical_unit *lu =
  920 + container_of(work, struct sbp2_logical_unit, work.work);
  921 + struct sbp2_target *tgt = lu->tgt;
  922 + struct fw_device *device = target_device(tgt);
  923 + int generation, node_id, local_node_id;
  924 +
  925 + if (fw_device_is_shutdown(device))
  926 + return;
  927 +
  928 + generation = device->generation;
  929 + smp_rmb(); /* node IDs must not be older than generation */
  930 + node_id = device->node_id;
  931 + local_node_id = device->card->node_id;
  932 +
  933 + if (sbp2_send_management_orb(lu, node_id, generation,
  934 + SBP2_RECONNECT_REQUEST,
  935 + lu->login_id, NULL) < 0) {
  936 + /*
  937 + * If reconnect was impossible even though we are in the
  938 + * current generation, fall back and try to log in again.
  939 + *
  940 + * We could check for "Function rejected" status, but
  941 + * looking at the bus generation as simpler and more general.
  942 + */
  943 + smp_rmb(); /* get current card generation */
  944 + if (generation == device->card->generation ||
  945 + lu->retries++ >= 5) {
  946 + fw_error("%s: failed to reconnect\n", tgt->bus_id);
  947 + lu->retries = 0;
  948 + PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
  949 + }
  950 + sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
  951 +
  952 + return;
  953 + }
  954 +
  955 + tgt->node_id = node_id;
  956 + tgt->address_high = local_node_id << 16;
  957 + smp_wmb(); /* node IDs must not be older than generation */
  958 + lu->generation = generation;
  959 +
  960 + fw_notify("%s: reconnected to LUN %04x (%d retries)\n",
  961 + tgt->bus_id, lu->lun, lu->retries);
  962 +
  963 + sbp2_agent_reset(lu);
  964 + sbp2_cancel_orbs(lu);
  965 + sbp2_conditionally_unblock(lu);
  966 +}
  967 +
958 968 static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
959 969 {
960 970 struct sbp2_logical_unit *lu;
... ... @@ -1100,6 +1110,7 @@
1100 1110 }
1101 1111  
1102 1112 static struct scsi_host_template scsi_driver_template;
  1113 +static void sbp2_release_target(struct sbp2_target *tgt);
1103 1114  
1104 1115 static int sbp2_probe(struct device *dev)
1105 1116 {
1106 1117  
1107 1118  
1108 1119  
1109 1120  
1110 1121  
1111 1122  
1112 1123  
1113 1124  
1114 1125  
1115 1126  
1116 1127  
1117 1128  
1118 1129  
1119 1130  
1120 1131  
... ... @@ -1171,87 +1182,77 @@
1171 1182 return -ENOMEM;
1172 1183 }
1173 1184  
1174   -static int sbp2_remove(struct device *dev)
  1185 +static void sbp2_update(struct fw_unit *unit)
1175 1186 {
1176   - struct fw_unit *unit = fw_unit(dev);
1177 1187 struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
1178 1188 struct sbp2_logical_unit *lu;
1179 1189  
1180   - list_for_each_entry(lu, &tgt->lu_list, link)
1181   - cancel_delayed_work_sync(&lu->work);
  1190 + fw_device_enable_phys_dma(fw_parent_device(unit));
1182 1191  
1183   - sbp2_release_target(tgt);
1184   -
1185   - return 0;
  1192 + /*
  1193 + * Fw-core serializes sbp2_update() against sbp2_remove().
  1194 + * Iteration over tgt->lu_list is therefore safe here.
  1195 + */
  1196 + list_for_each_entry(lu, &tgt->lu_list, link) {
  1197 + sbp2_conditionally_block(lu);
  1198 + lu->retries = 0;
  1199 + sbp2_queue_work(lu, 0);
  1200 + }
1186 1201 }
1187 1202  
1188   -static void sbp2_reconnect(struct work_struct *work)
  1203 +static void sbp2_release_target(struct sbp2_target *tgt)
1189 1204 {
1190   - struct sbp2_logical_unit *lu =
1191   - container_of(work, struct sbp2_logical_unit, work.work);
1192   - struct sbp2_target *tgt = lu->tgt;
  1205 + struct sbp2_logical_unit *lu, *next;
  1206 + struct Scsi_Host *shost =
  1207 + container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
  1208 + struct scsi_device *sdev;
1193 1209 struct fw_device *device = target_device(tgt);
1194   - int generation, node_id, local_node_id;
1195 1210  
1196   - if (fw_device_is_shutdown(device))
1197   - return;
  1211 + /* prevent deadlocks */
  1212 + sbp2_unblock(tgt);
1198 1213  
1199   - generation = device->generation;
1200   - smp_rmb(); /* node IDs must not be older than generation */
1201   - node_id = device->node_id;
1202   - local_node_id = device->card->node_id;
1203   -
1204   - if (sbp2_send_management_orb(lu, node_id, generation,
1205   - SBP2_RECONNECT_REQUEST,
1206   - lu->login_id, NULL) < 0) {
1207   - /*
1208   - * If reconnect was impossible even though we are in the
1209   - * current generation, fall back and try to log in again.
1210   - *
1211   - * We could check for "Function rejected" status, but
1212   - * looking at the bus generation as simpler and more general.
1213   - */
1214   - smp_rmb(); /* get current card generation */
1215   - if (generation == device->card->generation ||
1216   - lu->retries++ >= 5) {
1217   - fw_error("%s: failed to reconnect\n", tgt->bus_id);
1218   - lu->retries = 0;
1219   - PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
  1214 + list_for_each_entry_safe(lu, next, &tgt->lu_list, link) {
  1215 + sdev = scsi_device_lookup(shost, 0, 0, sbp2_lun2int(lu->lun));
  1216 + if (sdev) {
  1217 + scsi_remove_device(sdev);
  1218 + scsi_device_put(sdev);
1220 1219 }
1221   - sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
1222   -
1223   - return;
  1220 + if (lu->login_id != INVALID_LOGIN_ID) {
  1221 + int generation, node_id;
  1222 + /*
  1223 + * tgt->node_id may be obsolete here if we failed
  1224 + * during initial login or after a bus reset where
  1225 + * the topology changed.
  1226 + */
  1227 + generation = device->generation;
  1228 + smp_rmb(); /* node_id vs. generation */
  1229 + node_id = device->node_id;
  1230 + sbp2_send_management_orb(lu, node_id, generation,
  1231 + SBP2_LOGOUT_REQUEST,
  1232 + lu->login_id, NULL);
  1233 + }
  1234 + fw_core_remove_address_handler(&lu->address_handler);
  1235 + list_del(&lu->link);
  1236 + kfree(lu);
1224 1237 }
  1238 + scsi_remove_host(shost);
  1239 + fw_notify("released %s, target %d:0:0\n", tgt->bus_id, shost->host_no);
1225 1240  
1226   - tgt->node_id = node_id;
1227   - tgt->address_high = local_node_id << 16;
1228   - smp_wmb(); /* node IDs must not be older than generation */
1229   - lu->generation = generation;
1230   -
1231   - fw_notify("%s: reconnected to LUN %04x (%d retries)\n",
1232   - tgt->bus_id, lu->lun, lu->retries);
1233   -
1234   - sbp2_agent_reset(lu);
1235   - sbp2_cancel_orbs(lu);
1236   - sbp2_conditionally_unblock(lu);
  1241 + scsi_host_put(shost);
1237 1242 }
1238 1243  
1239   -static void sbp2_update(struct fw_unit *unit)
  1244 +static int sbp2_remove(struct device *dev)
1240 1245 {
  1246 + struct fw_unit *unit = fw_unit(dev);
1241 1247 struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
1242 1248 struct sbp2_logical_unit *lu;
1243 1249  
1244   - fw_device_enable_phys_dma(fw_parent_device(unit));
  1250 + list_for_each_entry(lu, &tgt->lu_list, link)
  1251 + cancel_delayed_work_sync(&lu->work);
1245 1252  
1246   - /*
1247   - * Fw-core serializes sbp2_update() against sbp2_remove().
1248   - * Iteration over tgt->lu_list is therefore safe here.
1249   - */
1250   - list_for_each_entry(lu, &tgt->lu_list, link) {
1251   - sbp2_conditionally_block(lu);
1252   - lu->retries = 0;
1253   - sbp2_queue_work(lu, 0);
1254   - }
  1253 + sbp2_release_target(tgt);
  1254 +
  1255 + return 0;
1255 1256 }
1256 1257  
1257 1258 #define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e