diff options
author | Joe Eykholt <jeykholt@cisco.com> | 2010-03-12 16:08:55 -0800 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-04-11 09:23:44 -0500 |
commit | f018b73af6db4f330ad5da9ac53997a699c30c42 (patch) | |
tree | 4f4e9405d923c0021771549dbdec34569c0e27a7 /drivers/scsi/libfc | |
parent | b3ef990c1514859bffae221b9e82e46a38f1e7bf (diff) |
[SCSI] libfc, libfcoe, fcoe: use smp_processor_id() only when preempt disabled
When the kernel is configured for preemption, using smp_processor_id()
when preemption is enabled causes a warning backtrace and is wrong
since we could move off of that CPU as soon as we get the ID,
and we would be referencing the wrong CPU, and possibly an invalid one
if it could be hotswapped out.
Remove the fc_lport_get_stats() function and explicitly use per_cpu_ptr()
to get the statistics. Where preemption has been disabled by holding
a _bh lock continue to use smp_processor_id(), but otherwise use
get_cpu()/put_cpu().
In fcoe_recv_frame() also changed the cases where we return in the
middle to do a goto to the code which bumps ErrorFrames and does
a put_cpu(). Two of these cases didn't bump ErrorFrames before, but
doing so is harmless because they "can't happen", due to prior length
checks.
Also rearranged code in fcoe_recv_frame() to have only one call to
fc_exch_recv(). It's just as efficient and saves a call to put_cpu().
In fc_fcp.c, adjusted a FIXME comment for code which doesn't need fixing.
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')
-rw-r--r-- | drivers/scsi/libfc/fc_exch.c | 3 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_fcp.c | 8 |
2 files changed, 7 insertions, 4 deletions
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index dc12a2bf0c9..d0496dafd84 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -676,9 +676,10 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport, } memset(ep, 0, sizeof(*ep)); - cpu = smp_processor_id(); + cpu = get_cpu(); pool = per_cpu_ptr(mp->pool, cpu); spin_lock_bh(&pool->lock); + put_cpu(); index = pool->next_index; /* allocate new exch from pool */ while (fc_exch_ptr_get(pool, index)) { diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 044c420a137..220c4bc536c 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -484,13 +484,14 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp) if (~crc != le32_to_cpu(fr_crc(fp))) { crc_err: - stats = fc_lport_get_stats(lport); + stats = per_cpu_ptr(lport->dev_stats, get_cpu()); stats->ErrorFrames++; - /* FIXME - per cpu count, not total count! */ + /* per cpu count, not total count, but OK for limit */ if (stats->InvalidCRCCount++ < 5) printk(KERN_WARNING "libfc: CRC error on data " "frame for port (%6x)\n", fc_host_port_id(lport->host)); + put_cpu(); /* * Assume the frame is total garbage. * We may have copied it over the good part @@ -1819,7 +1820,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *)) /* * setup the data direction */ - stats = fc_lport_get_stats(lport); + stats = per_cpu_ptr(lport->dev_stats, get_cpu()); if (sc_cmd->sc_data_direction == DMA_FROM_DEVICE) { fsp->req_flags = FC_SRB_READ; stats->InputRequests++; @@ -1832,6 +1833,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *)) fsp->req_flags = 0; stats->ControlRequests++; } + put_cpu(); fsp->tgt_flags = rpriv->flags; |