On Mon, 2009-08-10 at 10:17 -0700, Joe Eykholt wrote:
> 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 <[email protected]>
Hi Joe, I put Chris' latest NPIV prep work patches on and then started
applying and testing your patches. I get a NULL pointer exception when
the link comes up. At this point I don't know what it is.
Aug 12 10:02:32 localhost kernel: [77684.482050] libfc: Link up on port
( 0)
Aug 12 10:02:32 localhost kernel: [77684.483133] scsi179 : FCoE Driver
Aug 12 10:02:32 localhost kernel: [77684.483528] libfc: Link up on port
( 0)
Aug 12 10:03:43 localhost kernel: [77755.679258] scsi180 : FCoE Driver
Aug 12 10:03:43 localhost kernel: [77755.680037] libfc: Link up on port
( 0)
Aug 12 10:03:45 localhost kernel: [77757.676250] libfcoe: host180: FIP
selected Fibre-Channel Forwarder MAC 00:0d:ec:a3:1e:80
Aug 12 10:03:47 localhost kernel: [77759.689831] libfc: Assigned FID
(cf002e) in FLOGI response
Aug 12 10:03:47 localhost kernel: [77759.690373] BUG: unable to handle
kernel NULL pointer dereference at (null)
Aug 12 10:03:47 localhost kernel: [77759.690593] IP:
[<ffffffffa08fdf40>] fc_rport_work+0x9f/0x312 [libfc]
Aug 12 10:03:47 localhost kernel: [77759.690813] PGD 338871067 PUD
33508d067 PMD 0
Aug 12 10:03:47 localhost kernel: [77759.691030] Oops: 0000 [#1] SMP
Aug 12 10:03:47 localhost kernel: [77759.691243] last sysfs
file: /sys/module/fcoe/parameters/create
Aug 12 10:03:47 localhost kernel: [77759.691454] CPU 6
Aug 12 10:03:47 localhost kernel: [77759.691660] Modules linked in: fcoe
libfcoe libfc scsi_transport_fc netconsole ixgbe mdio [last unloaded:
scsi_transport_fc]
Aug 12 10:03:47 localhost kernel: [77759.692102] Pid: 11919, comm:
fc_rport_eq Not tainted 2.6.31-rc4 #1 X8DT3
Aug 12 10:03:47 localhost kernel: [77759.692315] RIP:
0010:[<ffffffffa08fdf40>] [<ffffffffa08fdf40>] fc_rport_work+0x9f/0x312
[libfc]
Aug 12 10:03:47 localhost kernel: [77759.692735] RSP:
0018:ffff880305877d80 EFLAGS: 00010286
Aug 12 10:03:47 localhost kernel: [77759.692944] RAX: ffff88033a151000
RBX: ffff88033a157448 RCX: 0000000000000006
Aug 12 10:03:47 localhost kernel: [77759.693157] RDX: 0000000000000000
RSI: 0000000000000001 RDI: ffffffff81520625
Aug 12 10:03:47 localhost kernel: [77759.693368] RBP: ffff880305877df0
R08: 0000000000000000 R09: 0000000000000000
Aug 12 10:03:47 localhost kernel: [77759.693579] R10: ffff880330c50700
R11: ffff880330db26c8 R12: ffff88033a157580
Aug 12 10:03:47 localhost kernel: [77759.693790] R13: ffff880305877da0
R14: ffff880330a9a5c8 R15: ffff88033a157400
Aug 12 10:03:47 localhost kernel: [77759.694001] FS:
0000000000000000(0000) GS:ffff880028120000(0000) knlGS:0000000000000000
Aug 12 10:03:47 localhost kernel: [77759.694410] CS: 0010 DS: 0018 ES:
0018 CR0: 000000008005003b
Aug 12 10:03:47 localhost kernel: [77759.694619] CR2: 0000000000000000
CR3: 000000033e096000 CR4: 00000000000006a0
Aug 12 10:03:47 localhost kernel: [77759.694830] DR0: 0000000000000000
DR1: 0000000000000000 DR2: 0000000000000000
Aug 12 10:03:47 localhost kernel: [77759.695042] DR3: 0000000000000000
DR6: 00000000ffff0ff0 DR7: 0000000000000400
Aug 12 10:03:47 localhost kernel: [77759.695254] Process fc_rport_eq
(pid: 11919, threadinfo ffff880305876000, task ffff880338835050)
Aug 12 10:03:47 localhost kernel: [77759.695665] Stack:
Aug 12 10:03:47 localhost kernel: [77759.695868] 0000000100000000
ffffffffa0908310 0000000000000000 ffff88033a151000
Aug 12 10:03:47 localhost kernel: [77759.696090] <0> 2001000deca31e81
250d000deca31e80 0000000000fffffc 0000000010130540
Aug 12 10:03:47 localhost kernel: [77759.696512] <0> ffff880305877e70
ffff880305877ed8 ffffc90010130540 ffff88033a157588
Aug 12 10:03:47 localhost kernel: [77759.697141] Call Trace:
Aug 12 10:03:47 localhost kernel: [77759.697348] [<ffffffff8104de24>]
worker_thread+0x1fa/0x30a
Aug 12 10:03:47 localhost kernel: [77759.697557] [<ffffffff8104ddcd>] ?
worker_thread+0x1a3/0x30a
Aug 12 10:03:47 localhost kernel: [77759.697769] [<ffffffffa08fdea1>] ?
fc_rport_work+0x0/0x312 [libfc]
Aug 12 10:03:47 localhost kernel: [77759.697982] [<ffffffff8105264b>] ?
autoremove_wake_function+0x0/0x38
Aug 12 10:03:47 localhost kernel: [77759.698195] [<ffffffff81061c0f>] ?
trace_hardirqs_on+0xd/0xf
Aug 12 10:03:47 localhost kernel: [77759.698404] [<ffffffff8104dc2a>] ?
worker_thread+0x0/0x30a
Aug 12 10:03:47 localhost kernel: [77759.698612] [<ffffffff8105231e>]
kthread+0x88/0x90
Aug 12 10:03:47 localhost kernel: [77759.698822] [<ffffffff8100cb5a>]
child_rip+0xa/0x20
Aug 12 10:03:47 localhost kernel: [77759.699030] [<ffffffff81521fec>] ?
_spin_unlock_irq+0x2b/0x30
Aug 12 10:03:47 localhost kernel: [77759.699239] [<ffffffff8100c53c>] ?
restore_args+0x0/0x30
Aug 12 10:03:47 localhost kernel: [77759.699447] [<ffffffff8152485a>] ?
__atomic_notifier_call_chain+0x0/0x87
Aug 12 10:03:47 localhost kernel: [77759.699658] [<ffffffff81052296>] ?
kthread+0x0/0x90
Aug 12 10:03:47 localhost kernel: [77759.699866] [<ffffffff8100cb50>] ?
child_rip+0x0/0x20
Aug 12 10:03:47 localhost kernel: [77759.700074] Code: 00 00 e8 15 27 c2
e0 31 f6 49 8b 7e 10 4c 89 ea e8 98 99 fe ff 48 89 45 a8 48 85 c0 0f 84
68 01 00 00 48 8b 55 a0 b9 06 00 00 00 <8b> 02 4c 89 ee 48 8b 55 a8 48
8b 5a 38 89 02 48 8d 7b 18 48 89
Aug 12 10:03:47 localhost kernel: [77759.700895] RIP
[<ffffffffa08fdf40>] fc_rport_work+0x9f/0x312 [libfc]
Aug 12 10:03:47 localhost kernel: [77759.701112] RSP <ffff880305877d80>
Aug 12 10:03:47 localhost kernel: [77759.701318] CR2: 0000000000000000
Aug 12 10:03:47 localhost kernel: [77759.701765] ---[ end trace
1bff1fc97f1cf129 ]---
> ---
> drivers/scsi/libfc/fc_disc.c | 54 ++++++++--------------
> drivers/scsi/libfc/fc_lport.c | 14 ++----
> drivers/scsi/libfc/fc_rport.c | 99
> +++++++++++++++++++++++------------------
> include/scsi/libfc.h | 29 +++++++-----
> 4 files changed, 96 insertions(+), 100 deletions(-)
>
>
> diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
> index 4b1f9fa..5f839b6 100644
> --- a/drivers/scsi/libfc/fc_disc.c
> +++ b/drivers/scsi/libfc/fc_disc.c
> @@ -47,7 +47,7 @@
>
> static void fc_disc_gpn_ft_req(struct fc_disc *);
> static void fc_disc_gpn_ft_resp(struct fc_seq *, struct fc_frame *, void *);
> -static int fc_disc_new_target(struct fc_disc *, struct fc_rport *,
> +static int fc_disc_new_target(struct fc_disc *, struct fc_rport_priv *,
> struct fc_rport_identifiers *);
> static void fc_disc_done(struct fc_disc *);
> static void fc_disc_timeout(struct work_struct *);
> @@ -63,12 +63,10 @@ struct fc_rport_priv *fc_disc_lookup_rport(const struct
> fc_lport *lport,
> u32 port_id)
> {
> const struct fc_disc *disc = &lport->disc;
> - struct fc_rport *rport;
> struct fc_rport_priv *rdata;
>
> list_for_each_entry(rdata, &disc->rports, peers) {
> - rport = PRIV_TO_RPORT(rdata);
> - if (rport->port_id == port_id)
> + if (rdata->ids.port_id == port_id)
> return rdata;
> }
> return NULL;
> @@ -115,10 +113,9 @@ static void fc_disc_rport_callback(struct fc_lport
> *lport,
> enum fc_rport_event event)
> {
> struct fc_disc *disc = &lport->disc;
> - struct fc_rport *rport = PRIV_TO_RPORT(rdata);
>
> FC_DISC_DBG(disc, "Received a %d event for port (%6x)\n", event,
> - rport->port_id);
> + rdata->ids.port_id);
>
> switch (event) {
> case RPORT_EV_CREATED:
> @@ -320,8 +317,6 @@ static void fc_disc_start(void (*disc_callback)(struct
> fc_lport *,
> struct fc_lport *lport)
> {
> struct fc_rport_priv *rdata;
> - struct fc_rport *rport;
> - struct fc_rport_identifiers ids;
> struct fc_disc *disc = &lport->disc;
>
> /*
> @@ -349,18 +344,12 @@ static void fc_disc_start(void (*disc_callback)(struct
> fc_lport *,
> */
> rdata = disc->lport->ptp_rp;
> if (rdata) {
> - rport = PRIV_TO_RPORT(rdata);
> - ids.port_id = rport->port_id;
> - ids.port_name = rport->port_name;
> - ids.node_name = rport->node_name;
> - ids.roles = FC_RPORT_ROLE_UNKNOWN;
> - get_device(&rport->dev);
> -
> - if (!fc_disc_new_target(disc, rport, &ids)) {
> + kref_get(&rdata->kref);
> + if (!fc_disc_new_target(disc, rdata, &rdata->ids)) {
> disc->event = DISC_EV_SUCCESS;
> fc_disc_done(disc);
> }
> - put_device(&rport->dev);
> + kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
> } else {
> fc_disc_gpn_ft_req(disc); /* get ports by FC-4 type */
> }
> @@ -375,28 +364,27 @@ static struct fc_rport_operations fc_disc_rport_ops = {
> /**
> * fc_disc_new_target() - Handle new target found by discovery
> * @lport: FC local port
> - * @rport: The previous FC remote port (NULL if new remote port)
> + * @rdata: The previous FC remote port priv (NULL if new remote port)
> * @ids: Identifiers for the new FC remote port
> *
> * Locking Note: This function expects that the disc_mutex is locked
> * before it is called.
> */
> static int fc_disc_new_target(struct fc_disc *disc,
> - struct fc_rport *rport,
> + struct fc_rport_priv *rdata,
> struct fc_rport_identifiers *ids)
> {
> struct fc_lport *lport = disc->lport;
> - struct fc_rport_priv *rdata;
> int error = 0;
>
> - if (rport && ids->port_name) {
> - if (rport->port_name == -1) {
> + if (rdata && ids->port_name) {
> + if (rdata->ids.port_name == -1) {
> /*
> * Set WWN and fall through to notify of create.
> */
> - fc_rport_set_name(rport, ids->port_name,
> - rport->node_name);
> - } else if (rport->port_name != ids->port_name) {
> + rdata->ids.port_name = ids->port_name;
> + rdata->ids.node_name = ids->node_name;
> + } else if (rdata->ids.port_name != ids->port_name) {
> /*
> * This is a new port with the same FCID as
> * a previously-discovered port. Presumably the old
> @@ -404,27 +392,23 @@ static int fc_disc_new_target(struct fc_disc *disc,
> * assigned the same FCID. This should be rare.
> * Delete the old one and fall thru to re-create.
> */
> - rdata = rport->dd_data;
> list_del(&rdata->peers);
> lport->tt.rport_logoff(rdata);
> - rport = NULL;
> + rdata = NULL;
> }
> }
> if (((ids->port_name != -1) || (ids->port_id != -1)) &&
> ids->port_id != fc_host_port_id(lport->host) &&
> ids->port_name != lport->wwpn) {
> - if (!rport) {
> + if (!rdata) {
> rdata = lport->tt.rport_lookup(lport, ids->port_id);
> - if (!rport) {
> + if (!rdata) {
> rdata = lport->tt.rport_create(lport, ids);
> + if (!rdata)
> + error = -ENOMEM;
> }
> - if (!rdata)
> - error = -ENOMEM;
> - else
> - rport = PRIV_TO_RPORT(rdata);
> }
> - if (rport) {
> - rdata = rport->dd_data;
> + if (rdata) {
> rdata->ops = &fc_disc_rport_ops;
> rdata->rp_state = RPORT_ST_INIT;
> list_add_tail(&rdata->peers, &disc->rogue_rports);
> diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
> index aa605d2..a7fe6b8 100644
> --- a/drivers/scsi/libfc/fc_lport.c
> +++ b/drivers/scsi/libfc/fc_lport.c
> @@ -143,14 +143,12 @@ static void fc_lport_rport_callback(struct fc_lport
> *lport,
> struct fc_rport_priv *rdata,
> enum fc_rport_event event)
> {
> - struct fc_rport *rport = PRIV_TO_RPORT(rdata);
> -
> FC_LPORT_DBG(lport, "Received a %d event for port (%6x)\n", event,
> - rport->port_id);
> + rdata->ids.port_id);
>
> switch (event) {
> case RPORT_EV_CREATED:
> - if (rport->port_id == FC_FID_DIR_SERV) {
> + if (rdata->ids.port_id == FC_FID_DIR_SERV) {
> mutex_lock(&lport->lp_mutex);
> if (lport->state == LPORT_ST_DNS) {
> lport->dns_rp = rdata;
> @@ -160,7 +158,7 @@ static void fc_lport_rport_callback(struct fc_lport
> *lport,
> "on port (%6x) for the directory "
> "server, but the lport is not "
> "in the DNS state, it's in the "
> - "%d state", rport->port_id,
> + "%d state", rdata->ids.port_id,
> lport->state);
> lport->tt.rport_logoff(rdata);
> }
> @@ -168,12 +166,12 @@ static void fc_lport_rport_callback(struct fc_lport
> *lport,
> } else
> FC_LPORT_DBG(lport, "Received an event for port (%6x) "
> "which is not the directory server\n",
> - rport->port_id);
> + rdata->ids.port_id);
> break;
> case RPORT_EV_LOGO:
> case RPORT_EV_FAILED:
> case RPORT_EV_STOP:
> - if (rport->port_id == FC_FID_DIR_SERV) {
> + if (rdata->ids.port_id == FC_FID_DIR_SERV) {
> mutex_lock(&lport->lp_mutex);
> lport->dns_rp = NULL;
> mutex_unlock(&lport->lp_mutex);
> @@ -181,7 +179,7 @@ static void fc_lport_rport_callback(struct fc_lport
> *lport,
> } else
> FC_LPORT_DBG(lport, "Received an event for port (%6x) "
> "which is not the directory server\n",
> - rport->port_id);
> + rdata->ids.port_id);
> break;
> case RPORT_EV_NONE:
> break;
> diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
> index 20371b4..2456407 100644
> --- a/drivers/scsi/libfc/fc_rport.c
> +++ b/drivers/scsi/libfc/fc_rport.c
> @@ -120,6 +120,8 @@ struct fc_rport_priv *fc_rport_rogue_create(struct
> fc_lport *lport,
> device_initialize(&rport->dev);
> rport->dev.release = fc_rport_rogue_destroy;
>
> + rdata->ids = *ids;
> + kref_init(&rdata->kref);
> mutex_init(&rdata->rp_mutex);
> rdata->local_port = lport;
> rdata->trans_state = FC_PORTSTATE_ROGUE;
> @@ -129,6 +131,7 @@ struct fc_rport_priv *fc_rport_rogue_create(struct
> fc_lport *lport,
> rdata->ops = NULL;
> rdata->e_d_tov = lport->e_d_tov;
> rdata->r_a_tov = lport->r_a_tov;
> + rdata->maxframe_size = FC_MIN_MAX_PAYLOAD;
> INIT_DELAYED_WORK(&rdata->retry_work, fc_rport_timeout);
> INIT_WORK(&rdata->event_work, fc_rport_work);
> /*
> @@ -141,6 +144,20 @@ struct fc_rport_priv *fc_rport_rogue_create(struct
> fc_lport *lport,
> }
>
> /**
> + * fc_rport_destroy() - free a remote port after last reference is released.
> + * @kref: pointer to kref inside struct fc_rport_priv
> + */
> +static void fc_rport_destroy(struct kref *kref)
> +{
> + struct fc_rport_priv *rdata;
> + struct fc_rport *rport;
> +
> + rdata = container_of(kref, struct fc_rport_priv, kref);
> + rport = rdata->rport;
> + put_device(&rport->dev);
> +}
> +
> +/**
> * fc_rport_state() - return a string for the state the rport is in
> * @rdata: remote port private data
> */
> @@ -215,22 +232,19 @@ static void fc_rport_work(struct work_struct *work)
> enum fc_rport_trans_state trans_state;
> struct fc_lport *lport = rdata->local_port;
> struct fc_rport_operations *rport_ops;
> - struct fc_rport *rport = PRIV_TO_RPORT(rdata);
> + struct fc_rport *rport;
>
> mutex_lock(&rdata->rp_mutex);
> event = rdata->event;
> rport_ops = rdata->ops;
> + rport = rdata->rport;
>
> if (event == RPORT_EV_CREATED) {
> struct fc_rport *new_rport;
> struct fc_rport_priv *new_rdata;
> struct fc_rport_identifiers ids;
>
> - ids.port_id = rport->port_id;
> - ids.roles = rport->roles;
> - ids.port_name = rport->port_name;
> - ids.node_name = rport->node_name;
> -
> + ids = rdata->ids;
> rdata->event = RPORT_EV_NONE;
> mutex_unlock(&rdata->rp_mutex);
>
> @@ -243,12 +257,17 @@ static void fc_rport_work(struct work_struct *work)
> new_rport->maxframe_size = rport->maxframe_size;
>
> new_rdata = new_rport->dd_data;
> + new_rdata->rport = new_rport;
> + new_rdata->ids = ids;
> new_rdata->e_d_tov = rdata->e_d_tov;
> new_rdata->r_a_tov = rdata->r_a_tov;
> new_rdata->ops = rdata->ops;
> new_rdata->local_port = rdata->local_port;
> new_rdata->flags = FC_RP_FLAGS_REC_SUPPORTED;
> new_rdata->trans_state = FC_PORTSTATE_REAL;
> + new_rdata->maxframe_size = rdata->maxframe_size;
> + new_rdata->supported_classes = rdata->supported_classes;
> + kref_init(&new_rdata->kref);
> mutex_init(&new_rdata->rp_mutex);
> INIT_DELAYED_WORK(&new_rdata->retry_work,
> fc_rport_timeout);
> @@ -261,12 +280,11 @@ static void fc_rport_work(struct work_struct *work)
> " memory for rport (%6x)\n", ids.port_id);
> event = RPORT_EV_FAILED;
> }
> - if (rport->port_id != FC_FID_DIR_SERV)
> + if (rdata->ids.port_id != FC_FID_DIR_SERV)
> if (rport_ops->event_callback)
> rport_ops->event_callback(lport, rdata,
> RPORT_EV_FAILED);
> - put_device(&rport->dev);
> - rport = new_rport;
> + kref_put(&rdata->kref, lport->tt.rport_destroy);
> rdata = new_rport->dd_data;
> if (rport_ops->event_callback)
> rport_ops->event_callback(lport, rdata, event);
> @@ -279,7 +297,7 @@ static void fc_rport_work(struct work_struct *work)
> rport_ops->event_callback(lport, rdata, event);
> cancel_delayed_work_sync(&rdata->retry_work);
> if (trans_state == FC_PORTSTATE_ROGUE)
> - put_device(&rport->dev);
> + kref_put(&rdata->kref, lport->tt.rport_destroy);
> else {
> port_id = rport->port_id;
> fc_remote_port_delete(rport);
> @@ -505,7 +523,6 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct
> fc_frame *fp,
> void *rdata_arg)
> {
> struct fc_rport_priv *rdata = rdata_arg;
> - struct fc_rport *rport = PRIV_TO_RPORT(rdata);
> struct fc_lport *lport = rdata->local_port;
> struct fc_els_flogi *plp = NULL;
> unsigned int tov;
> @@ -533,8 +550,8 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct
> fc_frame *fp,
> op = fc_frame_payload_op(fp);
> if (op == ELS_LS_ACC &&
> (plp = fc_frame_payload_get(fp, sizeof(*plp))) != NULL) {
> - rport->port_name = get_unaligned_be64(&plp->fl_wwpn);
> - rport->node_name = get_unaligned_be64(&plp->fl_wwnn);
> + rdata->ids.port_name = get_unaligned_be64(&plp->fl_wwpn);
> + rdata->ids.node_name = get_unaligned_be64(&plp->fl_wwnn);
>
> tov = ntohl(plp->fl_csp.sp_e_d_tov);
> if (ntohs(plp->fl_csp.sp_features) & FC_SP_FT_EDTR)
> @@ -546,14 +563,13 @@ static void fc_rport_plogi_resp(struct fc_seq *sp,
> struct fc_frame *fp,
> if (cssp_seq < csp_seq)
> csp_seq = cssp_seq;
> rdata->max_seq = csp_seq;
> - rport->maxframe_size =
> - fc_plogi_get_maxframe(plp, lport->mfs);
> + rdata->maxframe_size = fc_plogi_get_maxframe(plp, lport->mfs);
>
> /*
> * If the rport is one of the well known addresses
> * we skip PRLI and RTV and go straight to READY.
> */
> - if (rport->port_id >= FC_FID_DOM_MGR)
> + if (rdata->ids.port_id >= FC_FID_DOM_MGR)
> fc_rport_enter_ready(rdata);
> else
> fc_rport_enter_prli(rdata);
> @@ -564,7 +580,7 @@ out:
> fc_frame_free(fp);
> err:
> mutex_unlock(&rdata->rp_mutex);
> - put_device(&rport->dev);
> + kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
> }
>
> /**
> @@ -577,7 +593,6 @@ err:
> static void fc_rport_enter_plogi(struct fc_rport_priv *rdata)
> {
> struct fc_lport *lport = rdata->local_port;
> - struct fc_rport *rport = PRIV_TO_RPORT(rdata);
> struct fc_frame *fp;
>
> FC_RPORT_DBG(rdata, "Port entered PLOGI state from %s state\n",
> @@ -585,7 +600,7 @@ static void fc_rport_enter_plogi(struct fc_rport_priv
> *rdata)
>
> fc_rport_state_enter(rdata, RPORT_ST_PLOGI);
>
> - rport->maxframe_size = FC_MIN_MAX_PAYLOAD;
> + rdata->maxframe_size = FC_MIN_MAX_PAYLOAD;
> fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi));
> if (!fp) {
> fc_rport_error_retry(rdata, fp);
> @@ -593,11 +608,11 @@ static void fc_rport_enter_plogi(struct fc_rport_priv
> *rdata)
> }
> rdata->e_d_tov = lport->e_d_tov;
>
> - if (!lport->tt.elsct_send(lport, rport->port_id, fp, ELS_PLOGI,
> + if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PLOGI,
> fc_rport_plogi_resp, rdata, lport->e_d_tov))
> fc_rport_error_retry(rdata, fp);
> else
> - get_device(&rport->dev);
> + kref_get(&rdata->kref);
> }
>
> /**
> @@ -614,7 +629,6 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct
> fc_frame *fp,
> void *rdata_arg)
> {
> struct fc_rport_priv *rdata = rdata_arg;
> - struct fc_rport *rport = PRIV_TO_RPORT(rdata);
> struct {
> struct fc_els_prli prli;
> struct fc_els_spp spp;
> @@ -649,13 +663,13 @@ static void fc_rport_prli_resp(struct fc_seq *sp,
> struct fc_frame *fp,
> rdata->flags |= FC_RP_FLAGS_RETRY;
> }
>
> - rport->supported_classes = FC_COS_CLASS3;
> + rdata->supported_classes = FC_COS_CLASS3;
> if (fcp_parm & FCP_SPPF_INIT_FCN)
> roles |= FC_RPORT_ROLE_FCP_INITIATOR;
> if (fcp_parm & FCP_SPPF_TARG_FCN)
> roles |= FC_RPORT_ROLE_FCP_TARGET;
>
> - rport->roles = roles;
> + rdata->ids.roles = roles;
> fc_rport_enter_rtv(rdata);
>
> } else {
> @@ -667,7 +681,7 @@ out:
> fc_frame_free(fp);
> err:
> mutex_unlock(&rdata->rp_mutex);
> - put_device(&rport->dev);
> + kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
> }
>
> /**
> @@ -684,7 +698,6 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct
> fc_frame *fp,
> void *rdata_arg)
> {
> struct fc_rport_priv *rdata = rdata_arg;
> - struct fc_rport *rport = PRIV_TO_RPORT(rdata);
> u8 op;
>
> mutex_lock(&rdata->rp_mutex);
> @@ -716,7 +729,7 @@ out:
> fc_frame_free(fp);
> err:
> mutex_unlock(&rdata->rp_mutex);
> - put_device(&rport->dev);
> + kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
> }
>
> /**
> @@ -728,7 +741,6 @@ err:
> */
> static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
> {
> - struct fc_rport *rport = PRIV_TO_RPORT(rdata);
> struct fc_lport *lport = rdata->local_port;
> struct {
> struct fc_els_prli prli;
> @@ -747,11 +759,11 @@ static void fc_rport_enter_prli(struct fc_rport_priv
> *rdata)
> return;
> }
>
> - if (!lport->tt.elsct_send(lport, rport->port_id, fp, ELS_PRLI,
> + if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PRLI,
> fc_rport_prli_resp, rdata, lport->e_d_tov))
> fc_rport_error_retry(rdata, fp);
> else
> - get_device(&rport->dev);
> + kref_get(&rdata->kref);
> }
>
> /**
> @@ -770,7 +782,6 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct
> fc_frame *fp,
> void *rdata_arg)
> {
> struct fc_rport_priv *rdata = rdata_arg;
> - struct fc_rport *rport = PRIV_TO_RPORT(rdata);
> u8 op;
>
> mutex_lock(&rdata->rp_mutex);
> @@ -818,7 +829,7 @@ out:
> fc_frame_free(fp);
> err:
> mutex_unlock(&rdata->rp_mutex);
> - put_device(&rport->dev);
> + kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
> }
>
> /**
> @@ -832,7 +843,6 @@ static void fc_rport_enter_rtv(struct fc_rport_priv
> *rdata)
> {
> struct fc_frame *fp;
> struct fc_lport *lport = rdata->local_port;
> - struct fc_rport *rport = PRIV_TO_RPORT(rdata);
>
> FC_RPORT_DBG(rdata, "Port entered RTV state from %s state\n",
> fc_rport_state(rdata));
> @@ -845,11 +855,11 @@ static void fc_rport_enter_rtv(struct fc_rport_priv
> *rdata)
> return;
> }
>
> - if (!lport->tt.elsct_send(lport, rport->port_id, fp, ELS_RTV,
> + if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_RTV,
> fc_rport_rtv_resp, rdata, lport->e_d_tov))
> fc_rport_error_retry(rdata, fp);
> else
> - get_device(&rport->dev);
> + kref_get(&rdata->kref);
> }
>
> /**
> @@ -862,7 +872,6 @@ static void fc_rport_enter_rtv(struct fc_rport_priv
> *rdata)
> static void fc_rport_enter_logo(struct fc_rport_priv *rdata)
> {
> struct fc_lport *lport = rdata->local_port;
> - struct fc_rport *rport = PRIV_TO_RPORT(rdata);
> struct fc_frame *fp;
>
> FC_RPORT_DBG(rdata, "Port entered LOGO state from %s state\n",
> @@ -876,11 +885,11 @@ static void fc_rport_enter_logo(struct fc_rport_priv
> *rdata)
> return;
> }
>
> - if (!lport->tt.elsct_send(lport, rport->port_id, fp, ELS_LOGO,
> + if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_LOGO,
> fc_rport_logo_resp, rdata, lport->e_d_tov))
> fc_rport_error_retry(rdata, fp);
> else
> - get_device(&rport->dev);
> + kref_get(&rdata->kref);
> }
>
>
> @@ -956,7 +965,6 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame
> *fp,
> static void fc_rport_recv_plogi_req(struct fc_rport_priv *rdata,
> struct fc_seq *sp, struct fc_frame *rx_fp)
> {
> - struct fc_rport *rport = PRIV_TO_RPORT(rdata);
> struct fc_lport *lport = rdata->local_port;
> struct fc_frame *fp = rx_fp;
> struct fc_exch *ep;
> @@ -1041,12 +1049,13 @@ static void fc_rport_recv_plogi_req(struct
> fc_rport_priv *rdata,
> } else {
> sp = lport->tt.seq_start_next(sp);
> WARN_ON(!sp);
> - fc_rport_set_name(rport, wwpn, wwnn);
> + rdata->ids.port_name = wwpn;
> + rdata->ids.node_name = wwnn;
>
> /*
> * Get session payload size from incoming PLOGI.
> */
> - rport->maxframe_size =
> + rdata->maxframe_size =
> fc_plogi_get_maxframe(pl, lport->mfs);
> fc_frame_free(rx_fp);
> fc_plogi_fill(lport, fp, ELS_LS_ACC);
> @@ -1079,7 +1088,6 @@ static void fc_rport_recv_plogi_req(struct
> fc_rport_priv *rdata,
> static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
> struct fc_seq *sp, struct fc_frame *rx_fp)
> {
> - struct fc_rport *rport = PRIV_TO_RPORT(rdata);
> struct fc_lport *lport = rdata->local_port;
> struct fc_exch *ep;
> struct fc_frame *fp;
> @@ -1173,12 +1181,12 @@ static void fc_rport_recv_prli_req(struct
> fc_rport_priv *rdata,
> fcp_parm = ntohl(rspp->spp_params);
> if (fcp_parm * FCP_SPPF_RETRY)
> rdata->flags |= FC_RP_FLAGS_RETRY;
> - rport->supported_classes = FC_COS_CLASS3;
> + rdata->supported_classes = FC_COS_CLASS3;
> if (fcp_parm & FCP_SPPF_INIT_FCN)
> roles |= FC_RPORT_ROLE_FCP_INITIATOR;
> if (fcp_parm & FCP_SPPF_TARG_FCN)
> roles |= FC_RPORT_ROLE_FCP_TARGET;
> - rport->roles = roles;
> + rdata->ids.roles = roles;
>
> spp->spp_params =
> htonl(lport->service_params);
> @@ -1310,6 +1318,9 @@ int fc_rport_init(struct fc_lport *lport)
> if (!lport->tt.rport_flush_queue)
> lport->tt.rport_flush_queue = fc_rport_flush_queue;
>
> + if (!lport->tt.rport_destroy)
> + lport->tt.rport_destroy = fc_rport_destroy;
> +
> return 0;
> }
> EXPORT_SYMBOL(fc_rport_init);
> diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
> index 2473167..a94d216 100644
> --- a/include/scsi/libfc.h
> +++ b/include/scsi/libfc.h
> @@ -76,11 +76,7 @@ do {
> \
> (port_id), ##args))
>
> #define FC_RPORT_DBG(rdata, fmt, args...) \
> -do { \
> - struct fc_lport *lport = rdata->local_port; \
> - struct fc_rport *rport = PRIV_TO_RPORT(rdata); \
> - FC_RPORT_ID_DBG(lport, rport->port_id, fmt, ##args); \
> -} while (0)
> + FC_RPORT_ID_DBG((rdata)->local_port, (rdata)->ids.port_id, fmt, ##args)
>
> #define FC_FCP_DBG(pkt, fmt, args...)
> \
> FC_CHECK_LOGGING(FC_FCP_LOGGING, \
> @@ -195,9 +191,13 @@ struct fc_rport_operations {
> /**
> * struct fc_rport_libfc_priv - libfc internal information about a remote
> port
> * @local_port: Fibre Channel host port instance
> + * @rport: transport remote port
> + * @kref: reference counter
> * @rp_state: state tracks progress of PLOGI, PRLI, and RTV exchanges
> + * @ids: remote port identifiers and roles
> * @flags: REC and RETRY supported flags
> * @max_seq: maximum number of concurrent sequences
> + * @maxframe_size: maximum frame size
> * @retries: retry count in current state
> * @e_d_tov: error detect timeout value (in msec)
> * @r_a_tov: resource allocation timeout value (in msec)
> @@ -207,11 +207,15 @@ struct fc_rport_operations {
> */
> struct fc_rport_libfc_priv {
> struct fc_lport *local_port;
> + struct fc_rport *rport;
> + struct kref kref;
> enum fc_rport_state rp_state;
> + struct fc_rport_identifiers ids;
> u16 flags;
> #define FC_RP_FLAGS_REC_SUPPORTED (1 << 0)
> #define FC_RP_FLAGS_RETRY (1 << 1)
> u16 max_seq;
> + u16 maxframe_size;
> unsigned int retries;
> unsigned int e_d_tov;
> unsigned int r_a_tov;
> @@ -222,19 +226,12 @@ struct fc_rport_libfc_priv {
> struct fc_rport_operations *ops;
> struct list_head peers;
> struct work_struct event_work;
> + u32 supported_classes;
> };
>
> -#define PRIV_TO_RPORT(x) \
> - ((struct fc_rport *)((void *)(x) - sizeof(struct fc_rport)))
> #define RPORT_TO_PRIV(x) \
> ((struct fc_rport_libfc_priv *)((void *)(x) + sizeof(struct fc_rport)))
>
> -static inline void fc_rport_set_name(struct fc_rport *rport, u64 wwpn, u64
> wwnn)
> -{
> - rport->node_name = wwnn;
> - rport->port_name = wwpn;
> -}
> -
> /*
> * fcoe stats structure
> */
> @@ -609,6 +606,12 @@ struct libfc_function_template {
> struct fc_rport_priv *(*rport_lookup)(const struct fc_lport *, u32);
>
> /*
> + * Destroy an rport after final kref_put().
> + * The argument is a pointer to the kref inside the fc_rport_priv.
> + */
> + void (*rport_destroy)(struct kref *);
> +
> + /*
> * Send a fcp cmd from fsp pkt.
> * Called with the SCSI host lock unlocked and irqs disabled.
> *
>
>
> _______________________________________________
> devel mailing list
> [email protected]
> http://www.open-fcoe.org/mailman/listinfo/devel
_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel