aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libfc/fc_disc.c
diff options
context:
space:
mode:
authorJoe Eykholt <jeykholt@cisco.com>2009-08-25 17:01:01 -0400
committerJames Bottomley <James.Bottomley@suse.de>2009-09-10 13:07:42 -0400
commitf211fa514a07326c0f9364c0e6ed17e38860172f (patch)
tree9c2c54fee556816f36211185b6d6df0812b9acec /drivers/scsi/libfc/fc_disc.c
parenta46f327aa5caf2cce138e98ddd863b6cca0e71e2 (diff)
[SCSI] libfc: make rport structure optional
Allow a struct fc_rport_priv to have no fc_rport associated with it. This sets up to remove the need for "rogue" rports. Add a few fields to fc_rport_priv that are needed before the fc_rport is created. These are the ids, maxframe_size, classes, and rport pointer. Remove the macro PRIV_TO_RPORT(). Just use rdata->rport where appropriate. To take the place of the get_device()/put_device ops that were used to hold both the rport and rdata, add a reference count to rdata structures using kref. When kref_get decrements the refcount to zero, a new template function releasing the rdata should be called. This will take care of freeing the rdata and releasing the hold on the rport (for now). After subsequent patches make the rport truly optional, this release function will simply free the rdata. Remove the simple inline function fc_rport_set_name(), which becomes semanticly ambiguous otherwise. The caller will set the port_name and node_name in the rdata->Ids, which will later be copied to the rport when it its created. Signed-off-by: Joe Eykholt <jeykholt@cisco.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/libfc/fc_disc.c')
-rw-r--r--drivers/scsi/libfc/fc_disc.c54
1 files changed, 19 insertions, 35 deletions
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 4b1f9faf639a..5f839b625e50 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -47,7 +47,7 @@
47 47
48static void fc_disc_gpn_ft_req(struct fc_disc *); 48static void fc_disc_gpn_ft_req(struct fc_disc *);
49static void fc_disc_gpn_ft_resp(struct fc_seq *, struct fc_frame *, void *); 49static void fc_disc_gpn_ft_resp(struct fc_seq *, struct fc_frame *, void *);
50static int fc_disc_new_target(struct fc_disc *, struct fc_rport *, 50static int fc_disc_new_target(struct fc_disc *, struct fc_rport_priv *,
51 struct fc_rport_identifiers *); 51 struct fc_rport_identifiers *);
52static void fc_disc_done(struct fc_disc *); 52static void fc_disc_done(struct fc_disc *);
53static void fc_disc_timeout(struct work_struct *); 53static void fc_disc_timeout(struct work_struct *);
@@ -63,12 +63,10 @@ struct fc_rport_priv *fc_disc_lookup_rport(const struct fc_lport *lport,
63 u32 port_id) 63 u32 port_id)
64{ 64{
65 const struct fc_disc *disc = &lport->disc; 65 const struct fc_disc *disc = &lport->disc;
66 struct fc_rport *rport;
67 struct fc_rport_priv *rdata; 66 struct fc_rport_priv *rdata;
68 67
69 list_for_each_entry(rdata, &disc->rports, peers) { 68 list_for_each_entry(rdata, &disc->rports, peers) {
70 rport = PRIV_TO_RPORT(rdata); 69 if (rdata->ids.port_id == port_id)
71 if (rport->port_id == port_id)
72 return rdata; 70 return rdata;
73 } 71 }
74 return NULL; 72 return NULL;
@@ -115,10 +113,9 @@ static void fc_disc_rport_callback(struct fc_lport *lport,
115 enum fc_rport_event event) 113 enum fc_rport_event event)
116{ 114{
117 struct fc_disc *disc = &lport->disc; 115 struct fc_disc *disc = &lport->disc;
118 struct fc_rport *rport = PRIV_TO_RPORT(rdata);
119 116
120 FC_DISC_DBG(disc, "Received a %d event for port (%6x)\n", event, 117 FC_DISC_DBG(disc, "Received a %d event for port (%6x)\n", event,
121 rport->port_id); 118 rdata->ids.port_id);
122 119
123 switch (event) { 120 switch (event) {
124 case RPORT_EV_CREATED: 121 case RPORT_EV_CREATED:
@@ -320,8 +317,6 @@ static void fc_disc_start(void (*disc_callback)(struct fc_lport *,
320 struct fc_lport *lport) 317 struct fc_lport *lport)
321{ 318{
322 struct fc_rport_priv *rdata; 319 struct fc_rport_priv *rdata;
323 struct fc_rport *rport;
324 struct fc_rport_identifiers ids;
325 struct fc_disc *disc = &lport->disc; 320 struct fc_disc *disc = &lport->disc;
326 321
327 /* 322 /*
@@ -349,18 +344,12 @@ static void fc_disc_start(void (*disc_callback)(struct fc_lport *,
349 */ 344 */
350 rdata = disc->lport->ptp_rp; 345 rdata = disc->lport->ptp_rp;
351 if (rdata) { 346 if (rdata) {
352 rport = PRIV_TO_RPORT(rdata); 347 kref_get(&rdata->kref);
353 ids.port_id = rport->port_id; 348 if (!fc_disc_new_target(disc, rdata, &rdata->ids)) {
354 ids.port_name = rport->port_name;
355 ids.node_name = rport->node_name;
356 ids.roles = FC_RPORT_ROLE_UNKNOWN;
357 get_device(&rport->dev);
358
359 if (!fc_disc_new_target(disc, rport, &ids)) {
360 disc->event = DISC_EV_SUCCESS; 349 disc->event = DISC_EV_SUCCESS;
361 fc_disc_done(disc); 350 fc_disc_done(disc);
362 } 351 }
363 put_device(&rport->dev); 352 kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
364 } else { 353 } else {
365 fc_disc_gpn_ft_req(disc); /* get ports by FC-4 type */ 354 fc_disc_gpn_ft_req(disc); /* get ports by FC-4 type */
366 } 355 }
@@ -375,28 +364,27 @@ static struct fc_rport_operations fc_disc_rport_ops = {
375/** 364/**
376 * fc_disc_new_target() - Handle new target found by discovery 365 * fc_disc_new_target() - Handle new target found by discovery
377 * @lport: FC local port 366 * @lport: FC local port
378 * @rport: The previous FC remote port (NULL if new remote port) 367 * @rdata: The previous FC remote port priv (NULL if new remote port)
379 * @ids: Identifiers for the new FC remote port 368 * @ids: Identifiers for the new FC remote port
380 * 369 *
381 * Locking Note: This function expects that the disc_mutex is locked 370 * Locking Note: This function expects that the disc_mutex is locked
382 * before it is called. 371 * before it is called.
383 */ 372 */
384static int fc_disc_new_target(struct fc_disc *disc, 373static int fc_disc_new_target(struct fc_disc *disc,
385 struct fc_rport *rport, 374 struct fc_rport_priv *rdata,
386 struct fc_rport_identifiers *ids) 375 struct fc_rport_identifiers *ids)
387{ 376{
388 struct fc_lport *lport = disc->lport; 377 struct fc_lport *lport = disc->lport;
389 struct fc_rport_priv *rdata;
390 int error = 0; 378 int error = 0;
391 379
392 if (rport && ids->port_name) { 380 if (rdata && ids->port_name) {
393 if (rport->port_name == -1) { 381 if (rdata->ids.port_name == -1) {
394 /* 382 /*
395 * Set WWN and fall through to notify of create. 383 * Set WWN and fall through to notify of create.
396 */ 384 */
397 fc_rport_set_name(rport, ids->port_name, 385 rdata->ids.port_name = ids->port_name;
398 rport->node_name); 386 rdata->ids.node_name = ids->node_name;
399 } else if (rport->port_name != ids->port_name) { 387 } else if (rdata->ids.port_name != ids->port_name) {
400 /* 388 /*
401 * This is a new port with the same FCID as 389 * This is a new port with the same FCID as
402 * a previously-discovered port. Presumably the old 390 * a previously-discovered port. Presumably the old
@@ -404,27 +392,23 @@ static int fc_disc_new_target(struct fc_disc *disc,
404 * assigned the same FCID. This should be rare. 392 * assigned the same FCID. This should be rare.
405 * Delete the old one and fall thru to re-create. 393 * Delete the old one and fall thru to re-create.
406 */ 394 */
407 rdata = rport->dd_data;
408 list_del(&rdata->peers); 395 list_del(&rdata->peers);
409 lport->tt.rport_logoff(rdata); 396 lport->tt.rport_logoff(rdata);
410 rport = NULL; 397 rdata = NULL;
411 } 398 }
412 } 399 }
413 if (((ids->port_name != -1) || (ids->port_id != -1)) && 400 if (((ids->port_name != -1) || (ids->port_id != -1)) &&
414 ids->port_id != fc_host_port_id(lport->host) && 401 ids->port_id != fc_host_port_id(lport->host) &&
415 ids->port_name != lport->wwpn) { 402 ids->port_name != lport->wwpn) {
416 if (!rport) { 403 if (!rdata) {
417 rdata = lport->tt.rport_lookup(lport, ids->port_id); 404 rdata = lport->tt.rport_lookup(lport, ids->port_id);
418 if (!rport) { 405 if (!rdata) {
419 rdata = lport->tt.rport_create(lport, ids); 406 rdata = lport->tt.rport_create(lport, ids);
407 if (!rdata)
408 error = -ENOMEM;
420 } 409 }
421 if (!rdata)
422 error = -ENOMEM;
423 else
424 rport = PRIV_TO_RPORT(rdata);
425 } 410 }
426 if (rport) { 411 if (rdata) {
427 rdata = rport->dd_data;
428 rdata->ops = &fc_disc_rport_ops; 412 rdata->ops = &fc_disc_rport_ops;
429 rdata->rp_state = RPORT_ST_INIT; 413 rdata->rp_state = RPORT_ST_INIT;
430 list_add_tail(&rdata->peers, &disc->rogue_rports); 414 list_add_tail(&rdata->peers, &disc->rogue_rports);