Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (110 commits)
  [SCSI] qla2xxx: Refactor call to qla2xxx_read_sfp for thermal temperature.
  [SCSI] qla2xxx: Unify the read/write sfp mailbox command routines.
  [SCSI] qla2xxx: Clear complete initialization control block.
  [SCSI] qla2xxx: Allow an override of the registered maximum LUN.
  [SCSI] qla2xxx: Add host number in reset and quiescent message logs.
  [SCSI] qla2xxx: Correctly read sfp single byte mailbox register.
  [SCSI] qla2xxx: Add qla82xx_rom_unlock() function.
  [SCSI] qla2xxx: Log if qla82xx firmware fails to load from flash.
  [SCSI] qla2xxx: Use passed in host to initialize local scsi_qla_host in queuecommand function
  [SCSI] qla2xxx: Correct buffer start in edc sysfs debug print.
  [SCSI] qla2xxx: Update firmware version after flash update for ISP82xx.
  [SCSI] qla2xxx: Fix hang during driver unload when vport is active.
  [SCSI] qla2xxx: Properly set the dsd_list_len for dsd_chaining in cmd type 6.
  [SCSI] qla2xxx: Fix virtual port failing to login after chip reset.
  [SCSI] qla2xxx: Fix vport delete hang when logins are outstanding.
  [SCSI] hpsa: Change memset using sizeof(ptr) to sizeof(*ptr)
  [SCSI] ipr: Rate limit DMA mapping errors
  [SCSI] hpsa: add P2000 to list of shared SAS devices
  [SCSI] hpsa: do not attempt PCI power management reset method if we know it won't work.
  [SCSI] hpsa: remove superfluous sleeps around reset code
  ...
This commit is contained in:
Linus Torvalds 2011-05-20 13:29:52 -07:00
commit ad9471752e
119 changed files with 6398 additions and 1690 deletions

View File

@ -1,11 +1,11 @@
Copyright (c) 2003-2005 QLogic Corporation
QLogic Linux Fibre Channel HBA Driver
Copyright (c) 2003-2011 QLogic Corporation
QLogic Linux/ESX Fibre Channel HBA Driver
This program includes a device driver for Linux 2.6 that may be
This program includes a device driver for Linux 2.6/ESX that may be
distributed with QLogic hardware specific firmware binary file.
You may modify and redistribute the device driver code under the
GNU General Public License as published by the Free Software
Foundation (version 2 or a later version).
GNU General Public License (a copy of which is attached hereto as
Exhibit A) published by the Free Software Foundation (version 2).
You may redistribute the hardware specific firmware binary file
under the following terms:
@ -43,3 +43,285 @@ OTHERWISE IN ANY INTELLECTUAL PROPERTY RIGHTS (PATENT, COPYRIGHT,
TRADE SECRET, MASK WORK, OR OTHER PROPRIETARY RIGHT) EMBODIED IN
ANY OTHER QLOGIC HARDWARE OR SOFTWARE EITHER SOLELY OR IN
COMBINATION WITH THIS PROGRAM.
EXHIBIT A
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

View File

@ -5611,9 +5611,9 @@ F: include/linux/ata.h
F: include/linux/libata.h
SERVER ENGINES 10Gbps iSCSI - BladeEngine 2 DRIVER
M: Jayamohan Kallickal <jayamohank@serverengines.com>
M: Jayamohan Kallickal <jayamohan.kallickal@emulex.com>
L: linux-scsi@vger.kernel.org
W: http://www.serverengines.com
W: http://www.emulex.com
S: Supported
F: drivers/scsi/be2iscsi/

View File

@ -76,8 +76,8 @@
#define COPYRIGHT "Copyright (c) 1999-2008 " MODULEAUTHOR
#endif
#define MPT_LINUX_VERSION_COMMON "3.04.18"
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.18"
#define MPT_LINUX_VERSION_COMMON "3.04.19"
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.19"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \

View File

@ -5012,7 +5012,6 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
(ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)) {
VirtTarget *vtarget = NULL;
u8 id, channel;
u32 log_info = le32_to_cpu(reply->IOCLogInfo);
id = sas_event_data->TargetID;
channel = sas_event_data->Bus;
@ -5023,7 +5022,8 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
"LogInfo (0x%x) available for "
"INTERNAL_DEVICE_RESET"
"fw_id %d fw_channel %d\n", ioc->name,
log_info, id, channel));
le32_to_cpu(reply->IOCLogInfo),
id, channel));
if (vtarget->raidVolume) {
devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"Skipping Raid Volume for inDMD\n",

View File

@ -1415,11 +1415,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "qcmd: SCpnt=%p, done()=%p\n",
ioc->name, SCpnt, done));
if (ioc->taskmgmt_quiesce_io) {
dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
ioc->name, SCpnt));
if (ioc->taskmgmt_quiesce_io)
return SCSI_MLQUEUE_HOST_BUSY;
}
/*
* Put together a MPT SCSI request...
@ -1773,7 +1770,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
int scpnt_idx;
int retval;
VirtDevice *vdevice;
ulong sn = SCpnt->serial_number;
MPT_ADAPTER *ioc;
/* If we can't locate our host adapter structure, return FAILED status.
@ -1859,8 +1855,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
vdevice->vtarget->id, vdevice->lun,
ctx2abort, mptscsih_get_tm_timeout(ioc));
if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx &&
SCpnt->serial_number == sn) {
if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx) {
dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"task abort: command still in active list! (sc=%p)\n",
ioc->name, SCpnt));
@ -1873,9 +1868,9 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
}
out:
printk(MYIOC_s_INFO_FMT "task abort: %s (rv=%04x) (sc=%p) (sn=%ld)\n",
printk(MYIOC_s_INFO_FMT "task abort: %s (rv=%04x) (sc=%p)\n",
ioc->name, ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), retval,
SCpnt, SCpnt->serial_number);
SCpnt);
return retval;
}

View File

@ -867,6 +867,10 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget,
struct _x_config_parms cfg;
struct _CONFIG_PAGE_HEADER hdr;
int err = -EBUSY;
u32 nego_parms;
u32 period;
struct scsi_device *sdev;
int i;
/* don't allow updating nego parameters on RAID devices */
if (starget->channel == 0 &&
@ -904,6 +908,24 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget,
pg1->Header.PageNumber = hdr.PageNumber;
pg1->Header.PageType = hdr.PageType;
nego_parms = le32_to_cpu(pg1->RequestedParameters);
period = (nego_parms & MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK) >>
MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD;
if (period == 8) {
/* Turn on inline data padding for TAPE when running U320 */
for (i = 0 ; i < 16; i++) {
sdev = scsi_device_lookup_by_target(starget, i);
if (sdev && sdev->type == TYPE_TAPE) {
sdev_printk(KERN_DEBUG, sdev, MYIOC_s_FMT
"IDP:ON\n", ioc->name);
nego_parms |= MPI_SCSIDEVPAGE1_RP_IDP;
pg1->RequestedParameters =
cpu_to_le32(nego_parms);
break;
}
}
}
mptspi_print_write_nego(hd, starget, le32_to_cpu(pg1->RequestedParameters));
if (mpt_config(ioc, &cfg)) {

View File

@ -361,7 +361,7 @@ static int i2o_scsi_reply(struct i2o_controller *c, u32 m,
*/
error = le32_to_cpu(msg->body[0]);
osm_debug("Completed %ld\n", cmd->serial_number);
osm_debug("Completed %0x%p\n", cmd);
cmd->result = error & 0xff;
/*
@ -678,7 +678,7 @@ static int i2o_scsi_queuecommand_lck(struct scsi_cmnd *SCpnt,
/* Queue the message */
i2o_msg_post(c, msg);
osm_debug("Issued %ld\n", SCpnt->serial_number);
osm_debug("Issued %0x%p\n", SCpnt);
return 0;

View File

@ -75,8 +75,10 @@ MODULE_AUTHOR("Nick Cheng <support@areca.com.tw>");
MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/16xx/1880) SATA/SAS RAID Host Bus Adapter");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(ARCMSR_DRIVER_VERSION);
static int sleeptime = 10;
static int retrycount = 12;
#define ARCMSR_SLEEPTIME 10
#define ARCMSR_RETRYCOUNT 12
wait_queue_head_t wait_q;
static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb,
struct scsi_cmnd *cmd);
@ -171,24 +173,6 @@ static struct pci_driver arcmsr_pci_driver = {
****************************************************************************
****************************************************************************
*/
int arcmsr_sleep_for_bus_reset(struct scsi_cmnd *cmd)
{
struct Scsi_Host *shost = NULL;
int i, isleep;
shost = cmd->device->host;
isleep = sleeptime / 10;
if (isleep > 0) {
for (i = 0; i < isleep; i++) {
msleep(10000);
}
}
isleep = sleeptime % 10;
if (isleep > 0) {
msleep(isleep*1000);
}
return 0;
}
static void arcmsr_free_hbb_mu(struct AdapterControlBlock *acb)
{
@ -323,66 +307,64 @@ static void arcmsr_define_adapter_type(struct AdapterControlBlock *acb)
default: acb->adapter_type = ACB_ADAPTER_TYPE_A;
}
}
}
static uint8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb)
{
struct MessageUnit_A __iomem *reg = acb->pmuA;
uint32_t Index;
uint8_t Retries = 0x00;
do {
for (Index = 0; Index < 100; Index++) {
if (readl(&reg->outbound_intstatus) &
ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT,
&reg->outbound_intstatus);
return true;
}
msleep(10);
}/*max 1 seconds*/
int i;
for (i = 0; i < 2000; i++) {
if (readl(&reg->outbound_intstatus) &
ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT,
&reg->outbound_intstatus);
return true;
}
msleep(10);
} /* max 20 seconds */
} while (Retries++ < 20);/*max 20 sec*/
return false;
}
static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb)
{
struct MessageUnit_B *reg = acb->pmuB;
uint32_t Index;
uint8_t Retries = 0x00;
do {
for (Index = 0; Index < 100; Index++) {
if (readl(reg->iop2drv_doorbell)
& ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN
, reg->iop2drv_doorbell);
writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell);
return true;
}
msleep(10);
}/*max 1 seconds*/
int i;
for (i = 0; i < 2000; i++) {
if (readl(reg->iop2drv_doorbell)
& ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN,
reg->iop2drv_doorbell);
writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT,
reg->drv2iop_doorbell);
return true;
}
msleep(10);
} /* max 20 seconds */
} while (Retries++ < 20);/*max 20 sec*/
return false;
}
static uint8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *pACB)
{
struct MessageUnit_C *phbcmu = (struct MessageUnit_C *)pACB->pmuC;
unsigned char Retries = 0x00;
uint32_t Index;
do {
for (Index = 0; Index < 100; Index++) {
if (readl(&phbcmu->outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, &phbcmu->outbound_doorbell_clear);/*clear interrupt*/
return true;
}
/* one us delay */
msleep(10);
} /*max 1 seconds*/
} while (Retries++ < 20); /*max 20 sec*/
int i;
for (i = 0; i < 2000; i++) {
if (readl(&phbcmu->outbound_doorbell)
& ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR,
&phbcmu->outbound_doorbell_clear); /*clear interrupt*/
return true;
}
msleep(10);
} /* max 20 seconds */
return false;
}
static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb)
{
struct MessageUnit_A __iomem *reg = acb->pmuA;
@ -459,10 +441,11 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
struct CommandControlBlock *ccb_tmp;
int i = 0, j = 0;
dma_addr_t cdb_phyaddr;
unsigned long roundup_ccbsize = 0, offset;
unsigned long roundup_ccbsize;
unsigned long max_xfer_len;
unsigned long max_sg_entrys;
uint32_t firm_config_version;
for (i = 0; i < ARCMSR_MAX_TARGETID; i++)
for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++)
acb->devstate[i][j] = ARECA_RAID_GONE;
@ -472,23 +455,20 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
firm_config_version = acb->firm_cfg_version;
if((firm_config_version & 0xFF) >= 3){
max_xfer_len = (ARCMSR_CDB_SG_PAGE_LENGTH << ((firm_config_version >> 8) & 0xFF)) * 1024;/* max 4M byte */
max_sg_entrys = (max_xfer_len/4096);
max_sg_entrys = (max_xfer_len/4096);
}
acb->host->max_sectors = max_xfer_len/512;
acb->host->sg_tablesize = max_sg_entrys;
roundup_ccbsize = roundup(sizeof(struct CommandControlBlock) + (max_sg_entrys - 1) * sizeof(struct SG64ENTRY), 32);
acb->uncache_size = roundup_ccbsize * ARCMSR_MAX_FREECCB_NUM + 32;
acb->uncache_size = roundup_ccbsize * ARCMSR_MAX_FREECCB_NUM;
dma_coherent = dma_alloc_coherent(&pdev->dev, acb->uncache_size, &dma_coherent_handle, GFP_KERNEL);
if(!dma_coherent){
printk(KERN_NOTICE "arcmsr%d: dma_alloc_coherent got error \n", acb->host->host_no);
printk(KERN_NOTICE "arcmsr%d: dma_alloc_coherent got error\n", acb->host->host_no);
return -ENOMEM;
}
acb->dma_coherent = dma_coherent;
acb->dma_coherent_handle = dma_coherent_handle;
memset(dma_coherent, 0, acb->uncache_size);
offset = roundup((unsigned long)dma_coherent, 32) - (unsigned long)dma_coherent;
dma_coherent_handle = dma_coherent_handle + offset;
dma_coherent = (struct CommandControlBlock *)dma_coherent + offset;
ccb_tmp = dma_coherent;
acb->vir2phy_offset = (unsigned long)dma_coherent - (unsigned long)dma_coherent_handle;
for(i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++){
@ -2602,12 +2582,8 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb)
if (cdb_phyaddr_hi32 != 0) {
struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC;
if (cdb_phyaddr_hi32 != 0) {
unsigned char Retries = 0x00;
do {
printk(KERN_NOTICE "arcmsr%d: cdb_phyaddr_hi32=0x%x \n", acb->adapter_index, cdb_phyaddr_hi32);
} while (Retries++ < 100);
}
printk(KERN_NOTICE "arcmsr%d: cdb_phyaddr_hi32=0x%x\n",
acb->adapter_index, cdb_phyaddr_hi32);
writel(ARCMSR_SIGNATURE_SET_CONFIG, &reg->msgcode_rwbuffer[0]);
writel(cdb_phyaddr_hi32, &reg->msgcode_rwbuffer[1]);
writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, &reg->inbound_msgaddr0);
@ -2955,12 +2931,12 @@ static int arcmsr_bus_reset(struct scsi_cmnd *cmd)
arcmsr_hardware_reset(acb);
acb->acb_flags &= ~ACB_F_IOP_INITED;
sleep_again:
arcmsr_sleep_for_bus_reset(cmd);
ssleep(ARCMSR_SLEEPTIME);
if ((readl(&reg->outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) {
printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, retry=%d \n", acb->host->host_no, retry_count);
if (retry_count > retrycount) {
printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, retry=%d\n", acb->host->host_no, retry_count);
if (retry_count > ARCMSR_RETRYCOUNT) {
acb->fw_flag = FW_DEADLOCK;
printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, RETRY TERMINATED!! \n", acb->host->host_no);
printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, RETRY TERMINATED!!\n", acb->host->host_no);
return FAILED;
}
retry_count++;
@ -3025,12 +3001,12 @@ sleep_again:
arcmsr_hardware_reset(acb);
acb->acb_flags &= ~ACB_F_IOP_INITED;
sleep:
arcmsr_sleep_for_bus_reset(cmd);
ssleep(ARCMSR_SLEEPTIME);
if ((readl(&reg->host_diagnostic) & 0x04) != 0) {
printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, retry=%d \n", acb->host->host_no, retry_count);
if (retry_count > retrycount) {
printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, retry=%d\n", acb->host->host_no, retry_count);
if (retry_count > ARCMSR_RETRYCOUNT) {
acb->fw_flag = FW_DEADLOCK;
printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, RETRY TERMINATED!! \n", acb->host->host_no);
printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, RETRY TERMINATED!!\n", acb->host->host_no);
return FAILED;
}
retry_count++;

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2005 - 2010 ServerEngines
* Copyright (C) 2005 - 2011 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@ -8,11 +8,11 @@
* Public License is included in this distribution in the file called COPYING.
*
* Contact Information:
* linux-drivers@serverengines.com
* linux-drivers@emulex.com
*
* ServerEngines
* 209 N. Fair Oaks Ave
* Sunnyvale, CA 94085
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
#ifndef BEISCSI_H

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2005 - 2010 ServerEngines
* Copyright (C) 2005 - 2011 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@ -8,11 +8,11 @@
* Public License is included in this distribution in the file called COPYING.
*
* Contact Information:
* linux-drivers@serverengines.com
* linux-drivers@emulex.com
*
* ServerEngines
* 209 N. Fair Oaks Ave
* Sunnyvale, CA 94085
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
#include "be.h"
@ -458,6 +458,7 @@ void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
req_hdr->opcode = opcode;
req_hdr->subsystem = subsystem;
req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr));
req_hdr->timeout = 120;
}
static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages,

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2005 - 2010 ServerEngines
* Copyright (C) 2005 - 2011 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@ -8,11 +8,11 @@
* Public License is included in this distribution in the file called COPYING.
*
* Contact Information:
* linux-drivers@serverengines.com
* linux-drivers@emulex.com
*
* ServerEngines
* 209 N. Fair Oaks Ave
* Sunnyvale, CA 94085
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
#ifndef BEISCSI_CMDS_H

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2005 - 2010 ServerEngines
* Copyright (C) 2005 - 2011 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@ -7,15 +7,14 @@
* as published by the Free Software Foundation. The full GNU General
* Public License is included in this distribution in the file called COPYING.
*
* Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
* Written by: Jayamohan Kallickal (jayamohan.kallickal@emulex.com)
*
* Contact Information:
* linux-drivers@serverengines.com
*
* ServerEngines
* 209 N. Fair Oaks Ave
* Sunnyvale, CA 94085
* linux-drivers@emulex.com
*
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
#include <scsi/libiscsi.h>

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2005 - 2010 ServerEngines
* Copyright (C) 2005 - 2011 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@ -7,15 +7,14 @@
* as published by the Free Software Foundation. The full GNU General
* Public License is included in this distribution in the file called COPYING.
*
* Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
* Written by: Jayamohan Kallickal (jayamohan.kallickal@emulex.com)
*
* Contact Information:
* linux-drivers@serverengines.com
*
* ServerEngines
* 209 N. Fair Oaks Ave
* Sunnyvale, CA 94085
* linux-drivers@emulex.com
*
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
#ifndef _BE_ISCSI_

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2005 - 2010 ServerEngines
* Copyright (C) 2005 - 2011 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@ -7,16 +7,16 @@
* as published by the Free Software Foundation. The full GNU General
* Public License is included in this distribution in the file called COPYING.
*
* Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
* Written by: Jayamohan Kallickal (jayamohan.kallickal@emulex.com)
*
* Contact Information:
* linux-drivers@serverengines.com
*
* ServerEngines
* 209 N. Fair Oaks Ave
* Sunnyvale, CA 94085
* linux-drivers@emulex.com
*
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
#include <linux/reboot.h>
#include <linux/delay.h>
#include <linux/slab.h>
@ -420,7 +420,8 @@ static int beiscsi_setup_boot_info(struct beiscsi_hba *phba)
return 0;
free_kset:
iscsi_boot_destroy_kset(phba->boot_kset);
if (phba->boot_kset)
iscsi_boot_destroy_kset(phba->boot_kset);
return -ENOMEM;
}
@ -3464,23 +3465,23 @@ static void hwi_enable_intr(struct beiscsi_hba *phba)
addr = (u8 __iomem *) ((u8 __iomem *) ctrl->pcicfg +
PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET);
reg = ioread32(addr);
SE_DEBUG(DBG_LVL_8, "reg =x%08x\n", reg);
enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
if (!enabled) {
reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
SE_DEBUG(DBG_LVL_8, "reg =x%08x addr=%p\n", reg, addr);
iowrite32(reg, addr);
if (!phba->msix_enabled) {
eq = &phwi_context->be_eq[0].q;
}
if (!phba->msix_enabled) {
eq = &phwi_context->be_eq[0].q;
SE_DEBUG(DBG_LVL_8, "eq->id=%d\n", eq->id);
hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1);
} else {
for (i = 0; i <= phba->num_cpus; i++) {
eq = &phwi_context->be_eq[i].q;
SE_DEBUG(DBG_LVL_8, "eq->id=%d\n", eq->id);
hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1);
} else {
for (i = 0; i <= phba->num_cpus; i++) {
eq = &phwi_context->be_eq[i].q;
SE_DEBUG(DBG_LVL_8, "eq->id=%d\n", eq->id);
hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1);
}
}
}
}
@ -4019,12 +4020,17 @@ static int beiscsi_mtask(struct iscsi_task *task)
hwi_write_buffer(pwrb, task);
break;
case ISCSI_OP_NOOP_OUT:
AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
INI_RD_CMD);
if (task->hdr->ttt == ISCSI_RESERVED_TAG)
if (task->hdr->ttt != ISCSI_RESERVED_TAG) {
AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
TGT_DM_CMD);
AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt,
pwrb, 0);
AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);
else
} else {
AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,
INI_RD_CMD);
AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 1);
}
hwi_write_buffer(pwrb, task);
break;
case ISCSI_OP_TEXT:
@ -4144,10 +4150,11 @@ static void beiscsi_remove(struct pci_dev *pcidev)
phba->ctrl.mbox_mem_alloced.size,
phba->ctrl.mbox_mem_alloced.va,
phba->ctrl.mbox_mem_alloced.dma);
if (phba->boot_kset)
iscsi_boot_destroy_kset(phba->boot_kset);
iscsi_host_remove(phba->shost);
pci_dev_put(phba->pcidev);
iscsi_host_free(phba->shost);
iscsi_boot_destroy_kset(phba->boot_kset);
}
static void beiscsi_msix_enable(struct beiscsi_hba *phba)

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2005 - 2010 ServerEngines
* Copyright (C) 2005 - 2011 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@ -7,15 +7,14 @@
* as published by the Free Software Foundation. The full GNU General
* Public License is included in this distribution in the file called COPYING.
*
* Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
* Written by: Jayamohan Kallickal (jayamohan.kallickal@emulex.com)
*
* Contact Information:
* linux-drivers@serverengines.com
*
* ServerEngines
* 209 N. Fair Oaks Ave
* Sunnyvale, CA 94085
* linux-drivers@emulex.com
*
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
#ifndef _BEISCSI_MAIN_
@ -35,7 +34,7 @@
#include "be.h"
#define DRV_NAME "be2iscsi"
#define BUILD_STR "2.0.549.0"
#define BUILD_STR "2.103.298.0"
#define BE_NAME "ServerEngines BladeEngine2" \
"Linux iSCSI Driver version" BUILD_STR
#define DRV_DESC BE_NAME " " "Driver"

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2005 - 2010 ServerEngines
* Copyright (C) 2005 - 2011 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@ -7,15 +7,14 @@
* as published by the Free Software Foundation. The full GNU General
* Public License is included in this distribution in the file called COPYING.
*
* Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
* Written by: Jayamohan Kallickal (jayamohan.kallickal@emulex.com)
*
* Contact Information:
* linux-drivers@serverengines.com
*
* ServerEngines
* 209 N. Fair Oaks Ave
* Sunnyvale, CA 94085
* linux-drivers@emulex.com
*
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
#include "be_mgmt.h"
@ -203,8 +202,8 @@ int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute)
OPCODE_COMMON_ISCSI_CLEANUP, sizeof(*req));
req->chute = chute;
req->hdr_ring_id = 0;
req->data_ring_id = 0;
req->hdr_ring_id = cpu_to_le16(HWI_GET_DEF_HDRQ_ID(phba));
req->data_ring_id = cpu_to_le16(HWI_GET_DEF_BUFQ_ID(phba));
status = be_mcc_notify_wait(phba);
if (status)

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2005 - 2010 ServerEngines
* Copyright (C) 2005 - 2011 Emulex
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
@ -7,15 +7,14 @@
* as published by the Free Software Foundation. The full GNU General
* Public License is included in this distribution in the file called COPYING.
*
* Written by: Jayamohan Kallickal (jayamohank@serverengines.com)
* Written by: Jayamohan Kallickal (jayamohan.kallickal@emulex.com)
*
* Contact Information:
* linux-drivers@serverengines.com
*
* ServerEngines
* 209 N. Fair Oaks Ave
* Sunnyvale, CA 94085
* linux-drivers@emulex.com
*
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
*/
#ifndef _BEISCSI_MGMT_

View File

@ -57,9 +57,19 @@ int pcie_max_read_reqsz;
int bfa_debugfs_enable = 1;
int msix_disable_cb = 0, msix_disable_ct = 0;
/* Firmware releated */
u32 bfi_image_ct_fc_size, bfi_image_ct_cna_size, bfi_image_cb_fc_size;
u32 *bfi_image_ct_fc, *bfi_image_ct_cna, *bfi_image_cb_fc;
#define BFAD_FW_FILE_CT_FC "ctfw_fc.bin"
#define BFAD_FW_FILE_CT_CNA "ctfw_cna.bin"
#define BFAD_FW_FILE_CB_FC "cbfw_fc.bin"
static u32 *bfad_load_fwimg(struct pci_dev *pdev);
static void bfad_free_fwimg(void);
static void bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
u32 *bfi_image_size, char *fw_name);
static const char *msix_name_ct[] = {
"cpe0", "cpe1", "cpe2", "cpe3",
"rme0", "rme1", "rme2", "rme3",
@ -222,6 +232,9 @@ bfad_sm_created(struct bfad_s *bfad, enum bfad_sm_event event)
if ((bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
bfa_sm_send_event(bfad, BFAD_E_INIT_SUCCESS);
} else {
printk(KERN_WARNING
"bfa %s: bfa init failed\n",
bfad->pci_name);
bfad->bfad_flags |= BFAD_HAL_INIT_FAIL;
bfa_sm_send_event(bfad, BFAD_E_INIT_FAILED);
}
@ -991,10 +1004,6 @@ bfad_cfg_pport(struct bfad_s *bfad, enum bfa_lport_role role)
bfad->pport.roles |= BFA_LPORT_ROLE_FCP_IM;
}
/* Setup the debugfs node for this scsi_host */
if (bfa_debugfs_enable)
bfad_debugfs_init(&bfad->pport);
bfad->bfad_flags |= BFAD_CFG_PPORT_DONE;
out:
@ -1004,10 +1013,6 @@ out:
void
bfad_uncfg_pport(struct bfad_s *bfad)
{
/* Remove the debugfs node for this scsi_host */
kfree(bfad->regdata);
bfad_debugfs_exit(&bfad->pport);
if ((supported_fc4s & BFA_LPORT_ROLE_FCP_IM) &&
(bfad->pport.roles & BFA_LPORT_ROLE_FCP_IM)) {
bfad_im_scsi_host_free(bfad, bfad->pport.im_port);
@ -1389,6 +1394,10 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
bfad->pport.bfad = bfad;
INIT_LIST_HEAD(&bfad->pbc_vport_list);
/* Setup the debugfs node for this bfad */
if (bfa_debugfs_enable)
bfad_debugfs_init(&bfad->pport);
retval = bfad_drv_init(bfad);
if (retval != BFA_STATUS_OK)
goto out_drv_init_failure;
@ -1404,6 +1413,9 @@ out_bfad_sm_failure:
bfa_detach(&bfad->bfa);
bfad_hal_mem_release(bfad);
out_drv_init_failure:
/* Remove the debugfs node for this bfad */
kfree(bfad->regdata);
bfad_debugfs_exit(&bfad->pport);
mutex_lock(&bfad_mutex);
bfad_inst--;
list_del(&bfad->list_entry);
@ -1445,6 +1457,10 @@ bfad_pci_remove(struct pci_dev *pdev)
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
bfad_hal_mem_release(bfad);
/* Remove the debugfs node for this bfad */
kfree(bfad->regdata);
bfad_debugfs_exit(&bfad->pport);
/* Cleaning the BFAD instance */
mutex_lock(&bfad_mutex);
bfad_inst--;
@ -1550,7 +1566,7 @@ bfad_exit(void)
}
/* Firmware handling */
u32 *
static void
bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
u32 *bfi_image_size, char *fw_name)
{
@ -1558,27 +1574,25 @@ bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
if (request_firmware(&fw, fw_name, &pdev->dev)) {
printk(KERN_ALERT "Can't locate firmware %s\n", fw_name);
goto error;
*bfi_image = NULL;
goto out;
}
*bfi_image = vmalloc(fw->size);
if (NULL == *bfi_image) {
printk(KERN_ALERT "Fail to allocate buffer for fw image "
"size=%x!\n", (u32) fw->size);
goto error;
goto out;
}
memcpy(*bfi_image, fw->data, fw->size);
*bfi_image_size = fw->size/sizeof(u32);
return *bfi_image;
error:
return NULL;
out:
release_firmware(fw);
}
u32 *
bfad_get_firmware_buf(struct pci_dev *pdev)
static u32 *
bfad_load_fwimg(struct pci_dev *pdev)
{
if (pdev->device == BFA_PCI_DEVICE_ID_CT_FC) {
if (bfi_image_ct_fc_size == 0)
@ -1598,6 +1612,17 @@ bfad_get_firmware_buf(struct pci_dev *pdev)
}
}
static void
bfad_free_fwimg(void)
{
if (bfi_image_ct_fc_size && bfi_image_ct_fc)
vfree(bfi_image_ct_fc);
if (bfi_image_ct_cna_size && bfi_image_ct_cna)
vfree(bfi_image_ct_cna);
if (bfi_image_cb_fc_size && bfi_image_cb_fc)
vfree(bfi_image_cb_fc);
}
module_init(bfad_init);
module_exit(bfad_exit);
MODULE_LICENSE("GPL");

View File

@ -28,10 +28,10 @@
* mount -t debugfs none /sys/kernel/debug
*
* BFA Hierarchy:
* - bfa/host#
* where the host number corresponds to the one under /sys/class/scsi_host/host#
* - bfa/pci_dev:<pci_name>
* where the pci_name corresponds to the one under /sys/bus/pci/drivers/bfa
*
* Debugging service available per host:
* Debugging service available per pci_dev:
* fwtrc: To collect current firmware trace.
* drvtrc: To collect current driver trace
* fwsave: To collect last saved fw trace as a result of firmware crash.
@ -489,11 +489,9 @@ static atomic_t bfa_debugfs_port_count;
inline void
bfad_debugfs_init(struct bfad_port_s *port)
{
struct bfad_im_port_s *im_port = port->im_port;
struct bfad_s *bfad = im_port->bfad;
struct Scsi_Host *shost = im_port->shost;
struct bfad_s *bfad = port->bfad;
const struct bfad_debugfs_entry *file;
char name[16];
char name[64];
int i;
if (!bfa_debugfs_enable)
@ -510,17 +508,15 @@ bfad_debugfs_init(struct bfad_port_s *port)
}
}
/*
* Setup the host# directory for the port,
* corresponds to the scsi_host num of this port.
*/
snprintf(name, sizeof(name), "host%d", shost->host_no);
/* Setup the pci_dev debugfs directory for the port */
snprintf(name, sizeof(name), "pci_dev:%s", bfad->pci_name);
if (!port->port_debugfs_root) {
port->port_debugfs_root =
debugfs_create_dir(name, bfa_debugfs_root);
if (!port->port_debugfs_root) {
printk(KERN_WARNING
"BFA host root dir creation failed\n");
"bfa %s: debugfs root creation failed\n",
bfad->pci_name);
goto err;
}
@ -536,8 +532,8 @@ bfad_debugfs_init(struct bfad_port_s *port)
file->fops);
if (!bfad->bfad_dentry_files[i]) {
printk(KERN_WARNING
"BFA host%d: create %s entry failed\n",
shost->host_no, file->name);
"bfa %s: debugfs %s creation failed\n",
bfad->pci_name, file->name);
goto err;
}
}
@ -550,8 +546,7 @@ err:
inline void
bfad_debugfs_exit(struct bfad_port_s *port)
{
struct bfad_im_port_s *im_port = port->im_port;
struct bfad_s *bfad = im_port->bfad;
struct bfad_s *bfad = port->bfad;
int i;
for (i = 0; i < ARRAY_SIZE(bfad_debugfs_files); i++) {
@ -562,9 +557,7 @@ bfad_debugfs_exit(struct bfad_port_s *port)
}
/*
* Remove the host# directory for the port,
* corresponds to the scsi_host num of this port.
*/
* Remove the pci_dev debugfs directory for the port */
if (port->port_debugfs_root) {
debugfs_remove(port->port_debugfs_root);
port->port_debugfs_root = NULL;

View File

@ -141,29 +141,4 @@ extern struct device_attribute *bfad_im_vport_attrs[];
irqreturn_t bfad_intx(int irq, void *dev_id);
/* Firmware releated */
#define BFAD_FW_FILE_CT_FC "ctfw_fc.bin"
#define BFAD_FW_FILE_CT_CNA "ctfw_cna.bin"
#define BFAD_FW_FILE_CB_FC "cbfw_fc.bin"
u32 *bfad_get_firmware_buf(struct pci_dev *pdev);
u32 *bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
u32 *bfi_image_size, char *fw_name);
static inline u32 *
bfad_load_fwimg(struct pci_dev *pdev)
{
return bfad_get_firmware_buf(pdev);
}
static inline void
bfad_free_fwimg(void)
{
if (bfi_image_ct_fc_size && bfi_image_ct_fc)
vfree(bfi_image_ct_fc);
if (bfi_image_ct_cna_size && bfi_image_ct_cna)
vfree(bfi_image_ct_cna);
if (bfi_image_cb_fc_size && bfi_image_cb_fc)
vfree(bfi_image_cb_fc);
}
#endif

View File

@ -130,7 +130,7 @@
#define BNX2FC_TM_TIMEOUT 60 /* secs */
#define BNX2FC_IO_TIMEOUT 20000UL /* msecs */
#define BNX2FC_WAIT_CNT 120
#define BNX2FC_WAIT_CNT 1200
#define BNX2FC_FW_TIMEOUT (3 * HZ)
#define PORT_MAX 2

View File

@ -1130,7 +1130,7 @@ static void bnx2fc_interface_release(struct kref *kref)
struct net_device *phys_dev;
hba = container_of(kref, struct bnx2fc_hba, kref);
BNX2FC_HBA_DBG(hba->ctlr.lp, "Interface is being released\n");
BNX2FC_MISC_DBG("Interface is being released\n");
netdev = hba->netdev;
phys_dev = hba->phys_dev;
@ -1254,20 +1254,17 @@ setup_err:
static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
struct device *parent, int npiv)
{
struct fc_lport *lport = NULL;
struct fc_lport *lport, *n_port;
struct fcoe_port *port;
struct Scsi_Host *shost;
struct fc_vport *vport = dev_to_vport(parent);
int rc = 0;
/* Allocate Scsi_Host structure */
if (!npiv) {
lport = libfc_host_alloc(&bnx2fc_shost_template,
sizeof(struct fcoe_port));
} else {
lport = libfc_vport_create(vport,
sizeof(struct fcoe_port));
}
if (!npiv)
lport = libfc_host_alloc(&bnx2fc_shost_template, sizeof(*port));
else
lport = libfc_vport_create(vport, sizeof(*port));
if (!lport) {
printk(KERN_ERR PFX "could not allocate scsi host structure\n");
@ -1285,7 +1282,6 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
goto lp_config_err;
if (npiv) {
vport = dev_to_vport(parent);
printk(KERN_ERR PFX "Setting vport names, 0x%llX 0x%llX\n",
vport->node_name, vport->port_name);
fc_set_wwnn(lport, vport->node_name);
@ -1314,12 +1310,17 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
fc_host_port_type(lport->host) = FC_PORTTYPE_UNKNOWN;
/* Allocate exchange manager */
if (!npiv) {
if (!npiv)
rc = bnx2fc_em_config(lport);
if (rc) {
printk(KERN_ERR PFX "Error on bnx2fc_em_config\n");
goto shost_err;
}
else {
shost = vport_to_shost(vport);
n_port = shost_priv(shost);
rc = fc_exch_mgr_list_clone(n_port, lport);
}
if (rc) {
printk(KERN_ERR PFX "Error on bnx2fc_em_config\n");
goto shost_err;
}
bnx2fc_interface_get(hba);
@ -1352,8 +1353,6 @@ static void bnx2fc_if_destroy(struct fc_lport *lport)
/* Free existing transmit skbs */
fcoe_clean_pending_queue(lport);
bnx2fc_interface_put(hba);
/* Free queued packets for the receive thread */
bnx2fc_clean_rx_queue(lport);
@ -1372,6 +1371,8 @@ static void bnx2fc_if_destroy(struct fc_lport *lport)
/* Release Scsi_Host */
scsi_host_put(lport->host);
bnx2fc_interface_put(hba);
}
/**

View File

@ -522,6 +522,7 @@ void bnx2fc_process_l2_frame_compl(struct bnx2fc_rport *tgt,
fp = fc_frame_alloc(lport, payload_len);
if (!fp) {
printk(KERN_ERR PFX "fc_frame_alloc failure\n");
kfree(unsol_els);
return;
}
@ -547,6 +548,7 @@ void bnx2fc_process_l2_frame_compl(struct bnx2fc_rport *tgt,
*/
printk(KERN_ERR PFX "dropping ELS 0x%x\n", op);
kfree_skb(skb);
kfree(unsol_els);
return;
}
}
@ -563,6 +565,7 @@ void bnx2fc_process_l2_frame_compl(struct bnx2fc_rport *tgt,
} else {
BNX2FC_HBA_DBG(lport, "fh_r_ctl = 0x%x\n", fh->fh_r_ctl);
kfree_skb(skb);
kfree(unsol_els);
}
}

View File

@ -1663,6 +1663,12 @@ int bnx2fc_queuecommand(struct Scsi_Host *host,
tgt = (struct bnx2fc_rport *)&rp[1];
if (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) {
if (test_bit(BNX2FC_FLAG_UPLD_REQ_COMPL, &tgt->flags)) {
sc_cmd->result = DID_NO_CONNECT << 16;
sc_cmd->scsi_done(sc_cmd);
return 0;
}
/*
* Session is not offloaded yet. Let SCSI-ml retry
* the command.

View File

@ -772,6 +772,7 @@ static const struct error_info additional[] =
{0x3802, "Esn - power management class event"},
{0x3804, "Esn - media class event"},
{0x3806, "Esn - device busy class event"},
{0x3807, "Thin Provisioning soft threshold reached"},
{0x3900, "Saving parameters not supported"},

View File

@ -778,8 +778,8 @@ static void srb_free_insert(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
static void srb_waiting_insert(struct DeviceCtlBlk *dcb,
struct ScsiReqBlk *srb)
{
dprintkdbg(DBG_0, "srb_waiting_insert: (pid#%li) <%02i-%i> srb=%p\n",
srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb);
dprintkdbg(DBG_0, "srb_waiting_insert: (0x%p) <%02i-%i> srb=%p\n",
srb->cmd, dcb->target_id, dcb->target_lun, srb);
list_add(&srb->list, &dcb->srb_waiting_list);
}
@ -787,16 +787,16 @@ static void srb_waiting_insert(struct DeviceCtlBlk *dcb,
static void srb_waiting_append(struct DeviceCtlBlk *dcb,
struct ScsiReqBlk *srb)
{
dprintkdbg(DBG_0, "srb_waiting_append: (pid#%li) <%02i-%i> srb=%p\n",
srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb);
dprintkdbg(DBG_0, "srb_waiting_append: (0x%p) <%02i-%i> srb=%p\n",
srb->cmd, dcb->target_id, dcb->target_lun, srb);
list_add_tail(&srb->list, &dcb->srb_waiting_list);
}
static void srb_going_append(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb)
{
dprintkdbg(DBG_0, "srb_going_append: (pid#%li) <%02i-%i> srb=%p\n",
srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb);
dprintkdbg(DBG_0, "srb_going_append: (0x%p) <%02i-%i> srb=%p\n",
srb->cmd, dcb->target_id, dcb->target_lun, srb);
list_add_tail(&srb->list, &dcb->srb_going_list);
}
@ -805,8 +805,8 @@ static void srb_going_remove(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb)
{
struct ScsiReqBlk *i;
struct ScsiReqBlk *tmp;
dprintkdbg(DBG_0, "srb_going_remove: (pid#%li) <%02i-%i> srb=%p\n",
srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb);
dprintkdbg(DBG_0, "srb_going_remove: (0x%p) <%02i-%i> srb=%p\n",
srb->cmd, dcb->target_id, dcb->target_lun, srb);
list_for_each_entry_safe(i, tmp, &dcb->srb_going_list, list)
if (i == srb) {
@ -821,8 +821,8 @@ static void srb_waiting_remove(struct DeviceCtlBlk *dcb,
{
struct ScsiReqBlk *i;
struct ScsiReqBlk *tmp;
dprintkdbg(DBG_0, "srb_waiting_remove: (pid#%li) <%02i-%i> srb=%p\n",
srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb);
dprintkdbg(DBG_0, "srb_waiting_remove: (0x%p) <%02i-%i> srb=%p\n",
srb->cmd, dcb->target_id, dcb->target_lun, srb);
list_for_each_entry_safe(i, tmp, &dcb->srb_waiting_list, list)
if (i == srb) {
@ -836,8 +836,8 @@ static void srb_going_to_waiting_move(struct DeviceCtlBlk *dcb,
struct ScsiReqBlk *srb)
{
dprintkdbg(DBG_0,
"srb_going_to_waiting_move: (pid#%li) <%02i-%i> srb=%p\n",
srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb);
"srb_going_to_waiting_move: (0x%p) <%02i-%i> srb=%p\n",
srb->cmd, dcb->target_id, dcb->target_lun, srb);
list_move(&srb->list, &dcb->srb_waiting_list);
}
@ -846,8 +846,8 @@ static void srb_waiting_to_going_move(struct DeviceCtlBlk *dcb,
struct ScsiReqBlk *srb)
{
dprintkdbg(DBG_0,
"srb_waiting_to_going_move: (pid#%li) <%02i-%i> srb=%p\n",
srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb);
"srb_waiting_to_going_move: (0x%p) <%02i-%i> srb=%p\n",
srb->cmd, dcb->target_id, dcb->target_lun, srb);
list_move(&srb->list, &dcb->srb_going_list);
}
@ -982,8 +982,8 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
{
int nseg;
enum dma_data_direction dir = cmd->sc_data_direction;
dprintkdbg(DBG_0, "build_srb: (pid#%li) <%02i-%i>\n",
cmd->serial_number, dcb->target_id, dcb->target_lun);
dprintkdbg(DBG_0, "build_srb: (0x%p) <%02i-%i>\n",
cmd, dcb->target_id, dcb->target_lun);
srb->dcb = dcb;
srb->cmd = cmd;
@ -1086,8 +1086,8 @@ static int dc395x_queue_command_lck(struct scsi_cmnd *cmd, void (*done)(struct s
struct ScsiReqBlk *srb;
struct AdapterCtlBlk *acb =
(struct AdapterCtlBlk *)cmd->device->host->hostdata;
dprintkdbg(DBG_0, "queue_command: (pid#%li) <%02i-%i> cmnd=0x%02x\n",
cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
dprintkdbg(DBG_0, "queue_command: (0x%p) <%02i-%i> cmnd=0x%02x\n",
cmd, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
/* Assume BAD_TARGET; will be cleared later */
cmd->result = DID_BAD_TARGET << 16;
@ -1140,7 +1140,7 @@ static int dc395x_queue_command_lck(struct scsi_cmnd *cmd, void (*done)(struct s
/* process immediately */
send_srb(acb, srb);
}
dprintkdbg(DBG_1, "queue_command: (pid#%li) done\n", cmd->serial_number);
dprintkdbg(DBG_1, "queue_command: (0x%p) done\n", cmd);
return 0;
complete:
@ -1203,9 +1203,9 @@ static void dump_register_info(struct AdapterCtlBlk *acb,
dprintkl(KERN_INFO, "dump: srb=%p cmd=%p OOOPS!\n",
srb, srb->cmd);
else
dprintkl(KERN_INFO, "dump: srb=%p cmd=%p (pid#%li) "
dprintkl(KERN_INFO, "dump: srb=%p cmd=%p "
"cmnd=0x%02x <%02i-%i>\n",
srb, srb->cmd, srb->cmd->serial_number,
srb, srb->cmd,
srb->cmd->cmnd[0], srb->cmd->device->id,
srb->cmd->device->lun);
printk(" sglist=%p cnt=%i idx=%i len=%zu\n",
@ -1301,8 +1301,8 @@ static int __dc395x_eh_bus_reset(struct scsi_cmnd *cmd)
struct AdapterCtlBlk *acb =
(struct AdapterCtlBlk *)cmd->device->host->hostdata;
dprintkl(KERN_INFO,
"eh_bus_reset: (pid#%li) target=<%02i-%i> cmd=%p\n",
cmd->serial_number, cmd->device->id, cmd->device->lun, cmd);
"eh_bus_reset: (0%p) target=<%02i-%i> cmd=%p\n",
cmd, cmd->device->id, cmd->device->lun, cmd);
if (timer_pending(&acb->waiting_timer))
del_timer(&acb->waiting_timer);
@ -1368,8 +1368,8 @@ static int dc395x_eh_abort(struct scsi_cmnd *cmd)
(struct AdapterCtlBlk *)cmd->device->host->hostdata;
struct DeviceCtlBlk *dcb;
struct ScsiReqBlk *srb;
dprintkl(KERN_INFO, "eh_abort: (pid#%li) target=<%02i-%i> cmd=%p\n",
cmd->serial_number, cmd->device->id, cmd->device->lun, cmd);
dprintkl(KERN_INFO, "eh_abort: (0x%p) target=<%02i-%i> cmd=%p\n",
cmd, cmd->device->id, cmd->device->lun, cmd);
dcb = find_dcb(acb, cmd->device->id, cmd->device->lun);
if (!dcb) {
@ -1495,8 +1495,8 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb,
u16 s_stat2, return_code;
u8 s_stat, scsicommand, i, identify_message;
u8 *ptr;
dprintkdbg(DBG_0, "start_scsi: (pid#%li) <%02i-%i> srb=%p\n",
srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb);
dprintkdbg(DBG_0, "start_scsi: (0x%p) <%02i-%i> srb=%p\n",
dcb->target_id, dcb->target_lun, srb);
srb->tag_number = TAG_NONE; /* acb->tag_max_num: had error read in eeprom */
@ -1505,8 +1505,8 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb,
s_stat2 = DC395x_read16(acb, TRM_S1040_SCSI_STATUS);
#if 1
if (s_stat & 0x20 /* s_stat2 & 0x02000 */ ) {
dprintkdbg(DBG_KG, "start_scsi: (pid#%li) BUSY %02x %04x\n",
srb->cmd->serial_number, s_stat, s_stat2);
dprintkdbg(DBG_KG, "start_scsi: (0x%p) BUSY %02x %04x\n",
s_stat, s_stat2);
/*
* Try anyway?
*
@ -1522,16 +1522,15 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb,
}
#endif
if (acb->active_dcb) {
dprintkl(KERN_DEBUG, "start_scsi: (pid#%li) Attempt to start a"
"command while another command (pid#%li) is active.",
srb->cmd->serial_number,
dprintkl(KERN_DEBUG, "start_scsi: (0x%p) Attempt to start a"
"command while another command (0x%p) is active.",
srb->cmd,
acb->active_dcb->active_srb ?
acb->active_dcb->active_srb->cmd->serial_number : 0);
acb->active_dcb->active_srb->cmd : 0);
return 1;
}
if (DC395x_read16(acb, TRM_S1040_SCSI_STATUS) & SCSIINTERRUPT) {
dprintkdbg(DBG_KG, "start_scsi: (pid#%li) Failed (busy)\n",
srb->cmd->serial_number);
dprintkdbg(DBG_KG, "start_scsi: (0x%p) Failed (busy)\n", srb->cmd);
return 1;
}
/* Allow starting of SCSI commands half a second before we allow the mid-level
@ -1603,9 +1602,9 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb,
tag_number++;
}
if (tag_number >= dcb->max_command) {
dprintkl(KERN_WARNING, "start_scsi: (pid#%li) "
dprintkl(KERN_WARNING, "start_scsi: (0x%p) "
"Out of tags target=<%02i-%i>)\n",
srb->cmd->serial_number, srb->cmd->device->id,
srb->cmd, srb->cmd->device->id,
srb->cmd->device->lun);
srb->state = SRB_READY;
DC395x_write16(acb, TRM_S1040_SCSI_CONTROL,
@ -1623,8 +1622,8 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb,
#endif
/*polling:*/
/* Send CDB ..command block ......... */
dprintkdbg(DBG_KG, "start_scsi: (pid#%li) <%02i-%i> cmnd=0x%02x tag=%i\n",
srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun,
dprintkdbg(DBG_KG, "start_scsi: (0x%p) <%02i-%i> cmnd=0x%02x tag=%i\n",
srb->cmd, srb->cmd->device->id, srb->cmd->device->lun,
srb->cmd->cmnd[0], srb->tag_number);
if (srb->flag & AUTO_REQSENSE) {
DC395x_write8(acb, TRM_S1040_SCSI_FIFO, REQUEST_SENSE);
@ -1647,8 +1646,8 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb,
* we caught an interrupt (must be reset or reselection ... )
* : Let's process it first!
*/
dprintkdbg(DBG_0, "start_scsi: (pid#%li) <%02i-%i> Failed - busy\n",
srb->cmd->serial_number, dcb->target_id, dcb->target_lun);
dprintkdbg(DBG_0, "start_scsi: (0x%p) <%02i-%i> Failed - busy\n",
srb->cmd, dcb->target_id, dcb->target_lun);
srb->state = SRB_READY;
free_tag(dcb, srb);
srb->msg_count = 0;
@ -1843,7 +1842,7 @@ static irqreturn_t dc395x_interrupt(int irq, void *dev_id)
static void msgout_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 *pscsi_status)
{
dprintkdbg(DBG_0, "msgout_phase0: (pid#%li)\n", srb->cmd->serial_number);
dprintkdbg(DBG_0, "msgout_phase0: (0x%p)\n", srb->cmd);
if (srb->state & (SRB_UNEXPECT_RESEL + SRB_ABORT_SENT))
*pscsi_status = PH_BUS_FREE; /*.. initial phase */
@ -1857,18 +1856,18 @@ static void msgout_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
{
u16 i;
u8 *ptr;
dprintkdbg(DBG_0, "msgout_phase1: (pid#%li)\n", srb->cmd->serial_number);
dprintkdbg(DBG_0, "msgout_phase1: (0x%p)\n", srb->cmd);
clear_fifo(acb, "msgout_phase1");
if (!(srb->state & SRB_MSGOUT)) {
srb->state |= SRB_MSGOUT;
dprintkl(KERN_DEBUG,
"msgout_phase1: (pid#%li) Phase unexpected\n",
srb->cmd->serial_number); /* So what ? */
"msgout_phase1: (0x%p) Phase unexpected\n",
srb->cmd); /* So what ? */
}
if (!srb->msg_count) {
dprintkdbg(DBG_0, "msgout_phase1: (pid#%li) NOP msg\n",
srb->cmd->serial_number);
dprintkdbg(DBG_0, "msgout_phase1: (0x%p) NOP msg\n",
srb->cmd);
DC395x_write8(acb, TRM_S1040_SCSI_FIFO, MSG_NOP);
DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */
DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, SCMD_FIFO_OUT);
@ -1888,7 +1887,7 @@ static void msgout_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
static void command_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 *pscsi_status)
{
dprintkdbg(DBG_0, "command_phase0: (pid#%li)\n", srb->cmd->serial_number);
dprintkdbg(DBG_0, "command_phase0: (0x%p)\n", srb->cmd);
DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH);
}
@ -1899,7 +1898,7 @@ static void command_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
struct DeviceCtlBlk *dcb;
u8 *ptr;
u16 i;
dprintkdbg(DBG_0, "command_phase1: (pid#%li)\n", srb->cmd->serial_number);
dprintkdbg(DBG_0, "command_phase1: (0x%p)\n", srb->cmd);
clear_fifo(acb, "command_phase1");
DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_CLRATN);
@ -2041,8 +2040,8 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
struct DeviceCtlBlk *dcb = srb->dcb;
u16 scsi_status = *pscsi_status;
u32 d_left_counter = 0;
dprintkdbg(DBG_0, "data_out_phase0: (pid#%li) <%02i-%i>\n",
srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun);
dprintkdbg(DBG_0, "data_out_phase0: (0x%p) <%02i-%i>\n",
srb->cmd, srb->cmd->device->id, srb->cmd->device->lun);
/*
* KG: We need to drain the buffers before we draw any conclusions!
@ -2171,8 +2170,8 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
static void data_out_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 *pscsi_status)
{
dprintkdbg(DBG_0, "data_out_phase1: (pid#%li) <%02i-%i>\n",
srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun);
dprintkdbg(DBG_0, "data_out_phase1: (0x%p) <%02i-%i>\n",
srb->cmd, srb->cmd->device->id, srb->cmd->device->lun);
clear_fifo(acb, "data_out_phase1");
/* do prepare before transfer when data out phase */
data_io_transfer(acb, srb, XFERDATAOUT);
@ -2183,8 +2182,8 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
{
u16 scsi_status = *pscsi_status;
dprintkdbg(DBG_0, "data_in_phase0: (pid#%li) <%02i-%i>\n",
srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun);
dprintkdbg(DBG_0, "data_in_phase0: (0x%p) <%02i-%i>\n",
srb->cmd, srb->cmd->device->id, srb->cmd->device->lun);
/*
* KG: DataIn is much more tricky than DataOut. When the device is finished
@ -2204,8 +2203,8 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
unsigned int sc, fc;
if (scsi_status & PARITYERROR) {
dprintkl(KERN_INFO, "data_in_phase0: (pid#%li) "
"Parity Error\n", srb->cmd->serial_number);
dprintkl(KERN_INFO, "data_in_phase0: (0x%p) "
"Parity Error\n", srb->cmd);
srb->status |= PARITY_ERROR;
}
/*
@ -2394,8 +2393,8 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
static void data_in_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 *pscsi_status)
{
dprintkdbg(DBG_0, "data_in_phase1: (pid#%li) <%02i-%i>\n",
srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun);
dprintkdbg(DBG_0, "data_in_phase1: (0x%p) <%02i-%i>\n",
srb->cmd, srb->cmd->device->id, srb->cmd->device->lun);
data_io_transfer(acb, srb, XFERDATAIN);
}
@ -2406,8 +2405,8 @@ static void data_io_transfer(struct AdapterCtlBlk *acb,
struct DeviceCtlBlk *dcb = srb->dcb;
u8 bval;
dprintkdbg(DBG_0,
"data_io_transfer: (pid#%li) <%02i-%i> %c len=%i, sg=(%i/%i)\n",
srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun,
"data_io_transfer: (0x%p) <%02i-%i> %c len=%i, sg=(%i/%i)\n",
srb->cmd, srb->cmd->device->id, srb->cmd->device->lun,
((io_dir & DMACMD_DIR) ? 'r' : 'w'),
srb->total_xfer_length, srb->sg_index, srb->sg_count);
if (srb == acb->tmp_srb)
@ -2579,8 +2578,8 @@ static void data_io_transfer(struct AdapterCtlBlk *acb,
static void status_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 *pscsi_status)
{
dprintkdbg(DBG_0, "status_phase0: (pid#%li) <%02i-%i>\n",
srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun);
dprintkdbg(DBG_0, "status_phase0: (0x%p) <%02i-%i>\n",
srb->cmd, srb->cmd->device->id, srb->cmd->device->lun);
srb->target_status = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
srb->end_message = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); /* get message */
srb->state = SRB_COMPLETED;
@ -2593,8 +2592,8 @@ static void status_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
static void status_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 *pscsi_status)
{
dprintkdbg(DBG_0, "status_phase1: (pid#%li) <%02i-%i>\n",
srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun);
dprintkdbg(DBG_0, "status_phase1: (0x%p) <%02i-%i>\n",
srb->cmd, srb->cmd->device->id, srb->cmd->device->lun);
srb->state = SRB_STATUS;
DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */
DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, SCMD_COMP);
@ -2635,8 +2634,8 @@ static struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb,
{
struct ScsiReqBlk *srb = NULL;
struct ScsiReqBlk *i;
dprintkdbg(DBG_0, "msgin_qtag: (pid#%li) tag=%i srb=%p\n",
srb->cmd->serial_number, tag, srb);
dprintkdbg(DBG_0, "msgin_qtag: (0x%p) tag=%i srb=%p\n",
srb->cmd, tag, srb);
if (!(dcb->tag_mask & (1 << tag)))
dprintkl(KERN_DEBUG,
@ -2654,8 +2653,8 @@ static struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb,
if (!srb)
goto mingx0;
dprintkdbg(DBG_0, "msgin_qtag: (pid#%li) <%02i-%i>\n",
srb->cmd->serial_number, srb->dcb->target_id, srb->dcb->target_lun);
dprintkdbg(DBG_0, "msgin_qtag: (0x%p) <%02i-%i>\n",
srb->cmd, srb->dcb->target_id, srb->dcb->target_lun);
if (dcb->flag & ABORT_DEV_) {
/*srb->state = SRB_ABORT_SENT; */
enable_msgout_abort(acb, srb);
@ -2865,7 +2864,7 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 *pscsi_status)
{
struct DeviceCtlBlk *dcb = acb->active_dcb;
dprintkdbg(DBG_0, "msgin_phase0: (pid#%li)\n", srb->cmd->serial_number);
dprintkdbg(DBG_0, "msgin_phase0: (0x%p)\n", srb->cmd);
srb->msgin_buf[acb->msg_len++] = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
if (msgin_completed(srb->msgin_buf, acb->msg_len)) {
@ -2931,9 +2930,9 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
* SAVE POINTER may be ignored as we have the struct
* ScsiReqBlk* associated with the scsi command.
*/
dprintkdbg(DBG_0, "msgin_phase0: (pid#%li) "
dprintkdbg(DBG_0, "msgin_phase0: (0x%p) "
"SAVE POINTER rem=%i Ignore\n",
srb->cmd->serial_number, srb->total_xfer_length);
srb->cmd, srb->total_xfer_length);
break;
case RESTORE_POINTERS:
@ -2941,9 +2940,9 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
break;
case ABORT:
dprintkdbg(DBG_0, "msgin_phase0: (pid#%li) "
dprintkdbg(DBG_0, "msgin_phase0: (0x%p) "
"<%02i-%i> ABORT msg\n",
srb->cmd->serial_number, dcb->target_id,
srb->cmd, dcb->target_id,
dcb->target_lun);
dcb->flag |= ABORT_DEV_;
enable_msgout_abort(acb, srb);
@ -2975,7 +2974,7 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
static void msgin_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 *pscsi_status)
{
dprintkdbg(DBG_0, "msgin_phase1: (pid#%li)\n", srb->cmd->serial_number);
dprintkdbg(DBG_0, "msgin_phase1: (0x%p)\n", srb->cmd);
clear_fifo(acb, "msgin_phase1");
DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, 1);
if (!(srb->state & SRB_MSGIN)) {
@ -3041,7 +3040,7 @@ static void disconnect(struct AdapterCtlBlk *acb)
}
srb = dcb->active_srb;
acb->active_dcb = NULL;
dprintkdbg(DBG_0, "disconnect: (pid#%li)\n", srb->cmd->serial_number);
dprintkdbg(DBG_0, "disconnect: (0x%p)\n", srb->cmd);
srb->scsi_phase = PH_BUS_FREE; /* initial phase */
clear_fifo(acb, "disconnect");
@ -3071,14 +3070,14 @@ static void disconnect(struct AdapterCtlBlk *acb)
&& srb->state != SRB_MSGOUT) {
srb->state = SRB_READY;
dprintkl(KERN_DEBUG,
"disconnect: (pid#%li) Unexpected\n",
srb->cmd->serial_number);
"disconnect: (0x%p) Unexpected\n",
srb->cmd);
srb->target_status = SCSI_STAT_SEL_TIMEOUT;
goto disc1;
} else {
/* Normal selection timeout */
dprintkdbg(DBG_KG, "disconnect: (pid#%li) "
"<%02i-%i> SelTO\n", srb->cmd->serial_number,
dprintkdbg(DBG_KG, "disconnect: (0x%p) "
"<%02i-%i> SelTO\n", srb->cmd,
dcb->target_id, dcb->target_lun);
if (srb->retry_count++ > DC395x_MAX_RETRIES
|| acb->scan_devices) {
@ -3089,8 +3088,8 @@ static void disconnect(struct AdapterCtlBlk *acb)
free_tag(dcb, srb);
srb_going_to_waiting_move(dcb, srb);
dprintkdbg(DBG_KG,
"disconnect: (pid#%li) Retry\n",
srb->cmd->serial_number);
"disconnect: (0x%p) Retry\n",
srb->cmd);
waiting_set_timer(acb, HZ / 20);
}
} else if (srb->state & SRB_DISCONNECT) {
@ -3142,9 +3141,9 @@ static void reselect(struct AdapterCtlBlk *acb)
}
/* Why the if ? */
if (!acb->scan_devices) {
dprintkdbg(DBG_KG, "reselect: (pid#%li) <%02i-%i> "
dprintkdbg(DBG_KG, "reselect: (0x%p) <%02i-%i> "
"Arb lost but Resel win rsel=%i stat=0x%04x\n",
srb->cmd->serial_number, dcb->target_id,
srb->cmd, dcb->target_id,
dcb->target_lun, rsel_tar_lun_id,
DC395x_read16(acb, TRM_S1040_SCSI_STATUS));
arblostflag = 1;
@ -3318,7 +3317,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
enum dma_data_direction dir = cmd->sc_data_direction;
int ckc_only = 1;
dprintkdbg(DBG_1, "srb_done: (pid#%li) <%02i-%i>\n", srb->cmd->serial_number,
dprintkdbg(DBG_1, "srb_done: (0x%p) <%02i-%i>\n", srb->cmd,
srb->cmd->device->id, srb->cmd->device->lun);
dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p\n",
srb, scsi_sg_count(cmd), srb->sg_index, srb->sg_count,
@ -3497,9 +3496,9 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
cmd->SCp.buffers_residual = 0;
if (debug_enabled(DBG_KG)) {
if (srb->total_xfer_length)
dprintkdbg(DBG_KG, "srb_done: (pid#%li) <%02i-%i> "
dprintkdbg(DBG_KG, "srb_done: (0x%p) <%02i-%i> "
"cmnd=0x%02x Missed %i bytes\n",
cmd->serial_number, cmd->device->id, cmd->device->lun,
cmd, cmd->device->id, cmd->device->lun,
cmd->cmnd[0], srb->total_xfer_length);
}
@ -3508,8 +3507,8 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
if (srb == acb->tmp_srb)
dprintkl(KERN_ERR, "srb_done: ERROR! Completed cmd with tmp_srb\n");
else {
dprintkdbg(DBG_0, "srb_done: (pid#%li) done result=0x%08x\n",
cmd->serial_number, cmd->result);
dprintkdbg(DBG_0, "srb_done: (0x%p) done result=0x%08x\n",
cmd, cmd->result);
srb_free_insert(acb, srb);
}
pci_unmap_srb(acb, srb);
@ -3538,7 +3537,7 @@ static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag,
p = srb->cmd;
dir = p->sc_data_direction;
result = MK_RES(0, did_flag, 0, 0);
printk("G:%li(%02i-%i) ", p->serial_number,
printk("G:%p(%02i-%i) ", p,
p->device->id, p->device->lun);
srb_going_remove(dcb, srb);
free_tag(dcb, srb);
@ -3568,7 +3567,7 @@ static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag,
p = srb->cmd;
result = MK_RES(0, did_flag, 0, 0);
printk("W:%li<%02i-%i>", p->serial_number, p->device->id,
printk("W:%p<%02i-%i>", p, p->device->id,
p->device->lun);
srb_waiting_remove(dcb, srb);
srb_free_insert(acb, srb);
@ -3677,8 +3676,8 @@ static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
struct ScsiReqBlk *srb)
{
struct scsi_cmnd *cmd = srb->cmd;
dprintkdbg(DBG_1, "request_sense: (pid#%li) <%02i-%i>\n",
cmd->serial_number, cmd->device->id, cmd->device->lun);
dprintkdbg(DBG_1, "request_sense: (0x%p) <%02i-%i>\n",
cmd, cmd->device->id, cmd->device->lun);
srb->flag |= AUTO_REQSENSE;
srb->adapter_status = 0;
@ -3708,8 +3707,8 @@ static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
if (start_scsi(acb, dcb, srb)) { /* Should only happen, if sb. else grabs the bus */
dprintkl(KERN_DEBUG,
"request_sense: (pid#%li) failed <%02i-%i>\n",
srb->cmd->serial_number, dcb->target_id, dcb->target_lun);
"request_sense: (0x%p) failed <%02i-%i>\n",
srb->cmd, dcb->target_id, dcb->target_lun);
srb_going_to_waiting_move(dcb, srb);
waiting_set_timer(acb, HZ / 100);
}
@ -4717,13 +4716,13 @@ static int dc395x_proc_info(struct Scsi_Host *host, char *buffer,
dcb->target_id, dcb->target_lun,
list_size(&dcb->srb_waiting_list));
list_for_each_entry(srb, &dcb->srb_waiting_list, list)
SPRINTF(" %li", srb->cmd->serial_number);
SPRINTF(" %p", srb->cmd);
if (!list_empty(&dcb->srb_going_list))
SPRINTF("\nDCB (%02i-%i): Going : %i:",
dcb->target_id, dcb->target_lun,
list_size(&dcb->srb_going_list));
list_for_each_entry(srb, &dcb->srb_going_list, list)
SPRINTF(" %li", srb->cmd->serial_number);
SPRINTF(" %p", srb->cmd);
if (!list_empty(&dcb->srb_waiting_list) || !list_empty(&dcb->srb_going_list))
SPRINTF("\n");
}

View File

@ -782,7 +782,7 @@ static int alua_bus_attach(struct scsi_device *sdev)
h->sdev = sdev;
err = alua_initialize(sdev, h);
if (err != SCSI_DH_OK)
if ((err != SCSI_DH_OK) && (err != SCSI_DH_DEV_OFFLINED))
goto failed;
if (!try_module_get(THIS_MODULE))

View File

@ -182,14 +182,24 @@ struct rdac_dh_data {
struct rdac_controller *ctlr;
#define UNINITIALIZED_LUN (1 << 8)
unsigned lun;
#define RDAC_MODE 0
#define RDAC_MODE_AVT 1
#define RDAC_MODE_IOSHIP 2
unsigned char mode;
#define RDAC_STATE_ACTIVE 0
#define RDAC_STATE_PASSIVE 1
unsigned char state;
#define RDAC_LUN_UNOWNED 0
#define RDAC_LUN_OWNED 1
#define RDAC_LUN_AVT 2
char lun_state;
#define RDAC_PREFERRED 0
#define RDAC_NON_PREFERRED 1
char preferred;
unsigned char sense[SCSI_SENSE_BUFFERSIZE];
union {
struct c2_inquiry c2;
@ -199,11 +209,15 @@ struct rdac_dh_data {
} inq;
};
static const char *mode[] = {
"RDAC",
"AVT",
"IOSHIP",
};
static const char *lun_state[] =
{
"unowned",
"owned",
"owned (AVT mode)",
};
struct rdac_queue_data {
@ -458,25 +472,33 @@ static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h)
int err;
struct c9_inquiry *inqp;
h->lun_state = RDAC_LUN_UNOWNED;
h->state = RDAC_STATE_ACTIVE;
err = submit_inquiry(sdev, 0xC9, sizeof(struct c9_inquiry), h);
if (err == SCSI_DH_OK) {
inqp = &h->inq.c9;
if ((inqp->avte_cvp >> 7) == 0x1) {
/* LUN in AVT mode */
sdev_printk(KERN_NOTICE, sdev,
"%s: AVT mode detected\n",
RDAC_NAME);
h->lun_state = RDAC_LUN_AVT;
} else if ((inqp->avte_cvp & 0x1) != 0) {
/* LUN was owned by the controller */
h->lun_state = RDAC_LUN_OWNED;
}
}
/* detect the operating mode */
if ((inqp->avte_cvp >> 5) & 0x1)
h->mode = RDAC_MODE_IOSHIP; /* LUN in IOSHIP mode */
else if (inqp->avte_cvp >> 7)
h->mode = RDAC_MODE_AVT; /* LUN in AVT mode */
else
h->mode = RDAC_MODE; /* LUN in RDAC mode */
if (h->lun_state == RDAC_LUN_UNOWNED)
h->state = RDAC_STATE_PASSIVE;
/* Update ownership */
if (inqp->avte_cvp & 0x1)
h->lun_state = RDAC_LUN_OWNED;
else {
h->lun_state = RDAC_LUN_UNOWNED;
if (h->mode == RDAC_MODE)
h->state = RDAC_STATE_PASSIVE;
}
/* Update path prio*/
if (inqp->path_prio & 0x1)
h->preferred = RDAC_PREFERRED;
else
h->preferred = RDAC_NON_PREFERRED;
}
return err;
}
@ -648,12 +670,27 @@ static int rdac_activate(struct scsi_device *sdev,
{
struct rdac_dh_data *h = get_rdac_data(sdev);
int err = SCSI_DH_OK;
int act = 0;
err = check_ownership(sdev, h);
if (err != SCSI_DH_OK)
goto done;
if (h->lun_state == RDAC_LUN_UNOWNED) {
switch (h->mode) {
case RDAC_MODE:
if (h->lun_state == RDAC_LUN_UNOWNED)
act = 1;
break;
case RDAC_MODE_IOSHIP:
if ((h->lun_state == RDAC_LUN_UNOWNED) &&
(h->preferred == RDAC_PREFERRED))
act = 1;
break;
default:
break;
}
if (act) {
err = queue_mode_select(sdev, fn, data);
if (err == SCSI_DH_OK)
return 0;
@ -836,8 +873,9 @@ static int rdac_bus_attach(struct scsi_device *sdev)
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
sdev_printk(KERN_NOTICE, sdev,
"%s: LUN %d (%s)\n",
RDAC_NAME, h->lun, lun_state[(int)h->lun_state]);
"%s: LUN %d (%s) (%s)\n",
RDAC_NAME, h->lun, mode[(int)h->mode],
lun_state[(int)h->lun_state]);
return 0;

View File

@ -780,7 +780,7 @@ static int adpt_abort(struct scsi_cmnd * cmd)
return FAILED;
}
pHba = (adpt_hba*) cmd->device->host->hostdata[0];
printk(KERN_INFO"%s: Trying to Abort cmd=%ld\n",pHba->name, cmd->serial_number);
printk(KERN_INFO"%s: Trying to Abort\n",pHba->name);
if ((dptdevice = (void*) (cmd->device->hostdata)) == NULL) {
printk(KERN_ERR "%s: Unable to abort: No device in cmnd\n",pHba->name);
return FAILED;
@ -802,10 +802,10 @@ static int adpt_abort(struct scsi_cmnd * cmd)
printk(KERN_INFO"%s: Abort cmd not supported\n",pHba->name);
return FAILED;
}
printk(KERN_INFO"%s: Abort cmd=%ld failed.\n",pHba->name, cmd->serial_number);
printk(KERN_INFO"%s: Abort failed.\n",pHba->name);
return FAILED;
}
printk(KERN_INFO"%s: Abort cmd=%ld complete.\n",pHba->name, cmd->serial_number);
printk(KERN_INFO"%s: Abort complete.\n",pHba->name);
return SUCCESS;
}

View File

@ -1766,8 +1766,8 @@ static int eata2x_queuecommand_lck(struct scsi_cmnd *SCpnt,
struct mscp *cpp;
if (SCpnt->host_scribble)
panic("%s: qcomm, pid %ld, SCpnt %p already active.\n",
ha->board_name, SCpnt->serial_number, SCpnt);
panic("%s: qcomm, SCpnt %p already active.\n",
ha->board_name, SCpnt);
/* i is the mailbox number, look for the first free mailbox
starting from last_cp_used */
@ -1801,7 +1801,7 @@ static int eata2x_queuecommand_lck(struct scsi_cmnd *SCpnt,
if (do_trace)
scmd_printk(KERN_INFO, SCpnt,
"qcomm, mbox %d, pid %ld.\n", i, SCpnt->serial_number);
"qcomm, mbox %d.\n", i);
cpp->reqsen = 1;
cpp->dispri = 1;
@ -1833,8 +1833,7 @@ static int eata2x_queuecommand_lck(struct scsi_cmnd *SCpnt,
if (do_dma(shost->io_port, cpp->cp_dma_addr, SEND_CP_DMA)) {
unmap_dma(i, ha);
SCpnt->host_scribble = NULL;
scmd_printk(KERN_INFO, SCpnt,
"qcomm, pid %ld, adapter busy.\n", SCpnt->serial_number);
scmd_printk(KERN_INFO, SCpnt, "qcomm, adapter busy.\n");
return 1;
}
@ -1851,14 +1850,12 @@ static int eata2x_eh_abort(struct scsi_cmnd *SCarg)
unsigned int i;
if (SCarg->host_scribble == NULL) {
scmd_printk(KERN_INFO, SCarg,
"abort, pid %ld inactive.\n", SCarg->serial_number);
scmd_printk(KERN_INFO, SCarg, "abort, cmd inactive.\n");
return SUCCESS;
}
i = *(unsigned int *)SCarg->host_scribble;
scmd_printk(KERN_WARNING, SCarg,
"abort, mbox %d, pid %ld.\n", i, SCarg->serial_number);
scmd_printk(KERN_WARNING, SCarg, "abort, mbox %d.\n", i);
if (i >= shost->can_queue)
panic("%s: abort, invalid SCarg->host_scribble.\n", ha->board_name);
@ -1902,8 +1899,8 @@ static int eata2x_eh_abort(struct scsi_cmnd *SCarg)
SCarg->result = DID_ABORT << 16;
SCarg->host_scribble = NULL;
ha->cp_stat[i] = FREE;
printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n",
ha->board_name, i, SCarg->serial_number);
printk("%s, abort, mbox %d ready, DID_ABORT, done.\n",
ha->board_name, i);
SCarg->scsi_done(SCarg);
return SUCCESS;
}
@ -1919,13 +1916,12 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg)
struct Scsi_Host *shost = SCarg->device->host;
struct hostdata *ha = (struct hostdata *)shost->hostdata;
scmd_printk(KERN_INFO, SCarg,
"reset, enter, pid %ld.\n", SCarg->serial_number);
scmd_printk(KERN_INFO, SCarg, "reset, enter.\n");
spin_lock_irq(shost->host_lock);
if (SCarg->host_scribble == NULL)
printk("%s: reset, pid %ld inactive.\n", ha->board_name, SCarg->serial_number);
printk("%s: reset, inactive.\n", ha->board_name);
if (ha->in_reset) {
printk("%s: reset, exit, already in reset.\n", ha->board_name);
@ -1964,14 +1960,14 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg)
if (ha->cp_stat[i] == READY || ha->cp_stat[i] == ABORTING) {
ha->cp_stat[i] = ABORTING;
printk("%s: reset, mbox %d aborting, pid %ld.\n",
ha->board_name, i, SCpnt->serial_number);
printk("%s: reset, mbox %d aborting.\n",
ha->board_name, i);
}
else {
ha->cp_stat[i] = IN_RESET;
printk("%s: reset, mbox %d in reset, pid %ld.\n",
ha->board_name, i, SCpnt->serial_number);
printk("%s: reset, mbox %d in reset.\n",
ha->board_name, i);
}
if (SCpnt->host_scribble == NULL)
@ -2025,8 +2021,8 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg)
ha->cp_stat[i] = LOCKED;
printk
("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n",
ha->board_name, i, SCpnt->serial_number);
("%s, reset, mbox %d locked, DID_RESET, done.\n",
ha->board_name, i);
}
else if (ha->cp_stat[i] == ABORTING) {
@ -2039,8 +2035,8 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg)
ha->cp_stat[i] = FREE;
printk
("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n",
ha->board_name, i, SCpnt->serial_number);
("%s, reset, mbox %d aborting, DID_RESET, done.\n",
ha->board_name, i);
}
else
@ -2054,7 +2050,7 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg)
do_trace = 0;
if (arg_done)
printk("%s: reset, exit, pid %ld done.\n", ha->board_name, SCarg->serial_number);
printk("%s: reset, exit, done.\n", ha->board_name);
else
printk("%s: reset, exit.\n", ha->board_name);
@ -2238,10 +2234,10 @@ static int reorder(struct hostdata *ha, unsigned long cursec,
cpp = &ha->cp[k];
SCpnt = cpp->SCpnt;
scmd_printk(KERN_INFO, SCpnt,
"%s pid %ld mb %d fc %d nr %d sec %ld ns %u"
"%s mb %d fc %d nr %d sec %ld ns %u"
" cur %ld s:%c r:%c rev:%c in:%c ov:%c xd %d.\n",
(ihdlr ? "ihdlr" : "qcomm"),
SCpnt->serial_number, k, flushcount,
k, flushcount,
n_ready, blk_rq_pos(SCpnt->request),
blk_rq_sectors(SCpnt->request), cursec, YESNO(s),
YESNO(r), YESNO(rev), YESNO(input_only),
@ -2285,10 +2281,10 @@ static void flush_dev(struct scsi_device *dev, unsigned long cursec,
if (do_dma(dev->host->io_port, cpp->cp_dma_addr, SEND_CP_DMA)) {
scmd_printk(KERN_INFO, SCpnt,
"%s, pid %ld, mbox %d, adapter"
"%s, mbox %d, adapter"
" busy, will abort.\n",
(ihdlr ? "ihdlr" : "qcomm"),
SCpnt->serial_number, k);
k);
ha->cp_stat[k] = ABORTING;
continue;
}
@ -2398,12 +2394,12 @@ static irqreturn_t ihdlr(struct Scsi_Host *shost)
panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", ha->board_name, i);
if (SCpnt->host_scribble == NULL)
panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", ha->board_name,
i, SCpnt->serial_number, SCpnt);
panic("%s: ihdlr, mbox %d, SCpnt %p garbled.\n", ha->board_name,
i, SCpnt);
if (*(unsigned int *)SCpnt->host_scribble != i)
panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n",
ha->board_name, i, SCpnt->serial_number,
panic("%s: ihdlr, mbox %d, index mismatch %d.\n",
ha->board_name, i,
*(unsigned int *)SCpnt->host_scribble);
sync_dma(i, ha);
@ -2449,11 +2445,11 @@ static irqreturn_t ihdlr(struct Scsi_Host *shost)
if (spp->target_status && SCpnt->device->type == TYPE_DISK &&
(!(tstatus == CHECK_CONDITION && ha->iocount <= 1000 &&
(SCpnt->sense_buffer[2] & 0xf) == NOT_READY)))
printk("%s: ihdlr, target %d.%d:%d, pid %ld, "
printk("%s: ihdlr, target %d.%d:%d, "
"target_status 0x%x, sense key 0x%x.\n",
ha->board_name,
SCpnt->device->channel, SCpnt->device->id,
SCpnt->device->lun, SCpnt->serial_number,
SCpnt->device->lun,
spp->target_status, SCpnt->sense_buffer[2]);
ha->target_to[SCpnt->device->id][SCpnt->device->channel] = 0;
@ -2522,9 +2518,9 @@ static irqreturn_t ihdlr(struct Scsi_Host *shost)
do_trace || msg_byte(spp->target_status))
#endif
scmd_printk(KERN_INFO, SCpnt, "ihdlr, mbox %2d, err 0x%x:%x,"
" pid %ld, reg 0x%x, count %d.\n",
" reg 0x%x, count %d.\n",
i, spp->adapter_status, spp->target_status,
SCpnt->serial_number, reg, ha->iocount);
reg, ha->iocount);
unmap_dma(i, ha);

View File

@ -372,8 +372,7 @@ static int eata_pio_queue_lck(struct scsi_cmnd *cmd,
cp->status = USED; /* claim free slot */
DBG(DBG_QUEUE, scmd_printk(KERN_DEBUG, cmd,
"eata_pio_queue pid %ld, y %d\n",
cmd->serial_number, y));
"eata_pio_queue 0x%p, y %d\n", cmd, y));
cmd->scsi_done = (void *) done;
@ -417,8 +416,8 @@ static int eata_pio_queue_lck(struct scsi_cmnd *cmd,
if (eata_pio_send_command(base, EATA_CMD_PIO_SEND_CP)) {
cmd->result = DID_BUS_BUSY << 16;
scmd_printk(KERN_NOTICE, cmd,
"eata_pio_queue pid %ld, HBA busy, "
"returning DID_BUS_BUSY, done.\n", cmd->serial_number);
"eata_pio_queue pid 0x%p, HBA busy, "
"returning DID_BUS_BUSY, done.\n", cmd);
done(cmd);
cp->status = FREE;
return 0;
@ -432,8 +431,8 @@ static int eata_pio_queue_lck(struct scsi_cmnd *cmd,
outw(0, base + HA_RDATA);
DBG(DBG_QUEUE, scmd_printk(KERN_DEBUG, cmd,
"Queued base %#.4lx pid: %ld "
"slot %d irq %d\n", sh->base, cmd->serial_number, y, sh->irq));
"Queued base %#.4lx cmd: 0x%p "
"slot %d irq %d\n", sh->base, cmd, y, sh->irq));
return 0;
}
@ -445,8 +444,7 @@ static int eata_pio_abort(struct scsi_cmnd *cmd)
unsigned int loop = 100;
DBG(DBG_ABNORM, scmd_printk(KERN_WARNING, cmd,
"eata_pio_abort called pid: %ld\n",
cmd->serial_number));
"eata_pio_abort called pid: 0x%p\n", cmd));
while (inb(cmd->device->host->base + HA_RAUXSTAT) & HA_ABUSY)
if (--loop == 0) {
@ -481,8 +479,7 @@ static int eata_pio_host_reset(struct scsi_cmnd *cmd)
struct Scsi_Host *host = cmd->device->host;
DBG(DBG_ABNORM, scmd_printk(KERN_WARNING, cmd,
"eata_pio_reset called pid:%ld\n",
cmd->serial_number));
"eata_pio_reset called\n"));
spin_lock_irq(host->host_lock);
@ -501,7 +498,7 @@ static int eata_pio_host_reset(struct scsi_cmnd *cmd)
sp = HD(cmd)->ccb[x].cmd;
HD(cmd)->ccb[x].status = RESET;
printk(KERN_WARNING "eata_pio_reset: slot %d in reset, pid %ld.\n", x, sp->serial_number);
printk(KERN_WARNING "eata_pio_reset: slot %d in reset.\n", x);
if (sp == NULL)
panic("eata_pio_reset: slot %d, sp==NULL.\n", x);

View File

@ -708,8 +708,7 @@ static void esp_maybe_execute_command(struct esp *esp)
tp = &esp->target[tgt];
lp = dev->hostdata;
list_del(&ent->list);
list_add(&ent->list, &esp->active_cmds);
list_move(&ent->list, &esp->active_cmds);
esp->active_cmd = ent;
@ -1244,8 +1243,7 @@ static int esp_finish_select(struct esp *esp)
/* Now that the state is unwound properly, put back onto
* the issue queue. This command is no longer active.
*/
list_del(&ent->list);
list_add(&ent->list, &esp->queued_cmds);
list_move(&ent->list, &esp->queued_cmds);
esp->active_cmd = NULL;
/* Return value ignored by caller, it directly invokes

View File

@ -380,49 +380,6 @@ out:
return fcoe;
}
/**
* fcoe_interface_cleanup() - Clean up a FCoE interface
* @fcoe: The FCoE interface to be cleaned up
*
* Caller must be holding the RTNL mutex
*/
void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
{
struct net_device *netdev = fcoe->netdev;
struct fcoe_ctlr *fip = &fcoe->ctlr;
u8 flogi_maddr[ETH_ALEN];
const struct net_device_ops *ops;
/*
* Don't listen for Ethernet packets anymore.
* synchronize_net() ensures that the packet handlers are not running
* on another CPU. dev_remove_pack() would do that, this calls the
* unsyncronized version __dev_remove_pack() to avoid multiple delays.
*/
__dev_remove_pack(&fcoe->fcoe_packet_type);
__dev_remove_pack(&fcoe->fip_packet_type);
synchronize_net();
/* Delete secondary MAC addresses */
memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
dev_uc_del(netdev, flogi_maddr);
if (fip->spma)
dev_uc_del(netdev, fip->ctl_src_addr);
if (fip->mode == FIP_MODE_VN2VN) {
dev_mc_del(netdev, FIP_ALL_VN2VN_MACS);
dev_mc_del(netdev, FIP_ALL_P2P_MACS);
} else
dev_mc_del(netdev, FIP_ALL_ENODE_MACS);
/* Tell the LLD we are done w/ FCoE */
ops = netdev->netdev_ops;
if (ops->ndo_fcoe_disable) {
if (ops->ndo_fcoe_disable(netdev))
FCOE_NETDEV_DBG(netdev, "Failed to disable FCoE"
" specific feature for LLD.\n");
}
}
/**
* fcoe_interface_release() - fcoe_port kref release function
* @kref: Embedded reference count in an fcoe_interface struct
@ -459,6 +416,68 @@ static inline void fcoe_interface_put(struct fcoe_interface *fcoe)
kref_put(&fcoe->kref, fcoe_interface_release);
}
/**
* fcoe_interface_cleanup() - Clean up a FCoE interface
* @fcoe: The FCoE interface to be cleaned up
*
* Caller must be holding the RTNL mutex
*/
void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
{
struct net_device *netdev = fcoe->netdev;
struct fcoe_ctlr *fip = &fcoe->ctlr;
u8 flogi_maddr[ETH_ALEN];
const struct net_device_ops *ops;
struct fcoe_port *port = lport_priv(fcoe->ctlr.lp);
FCOE_NETDEV_DBG(netdev, "Destroying interface\n");
/* Logout of the fabric */
fc_fabric_logoff(fcoe->ctlr.lp);
/* Cleanup the fc_lport */
fc_lport_destroy(fcoe->ctlr.lp);
/* Stop the transmit retry timer */
del_timer_sync(&port->timer);
/* Free existing transmit skbs */
fcoe_clean_pending_queue(fcoe->ctlr.lp);
/*
* Don't listen for Ethernet packets anymore.
* synchronize_net() ensures that the packet handlers are not running
* on another CPU. dev_remove_pack() would do that, this calls the
* unsyncronized version __dev_remove_pack() to avoid multiple delays.
*/
__dev_remove_pack(&fcoe->fcoe_packet_type);
__dev_remove_pack(&fcoe->fip_packet_type);
synchronize_net();
/* Delete secondary MAC addresses */
memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
dev_uc_del(netdev, flogi_maddr);
if (fip->spma)
dev_uc_del(netdev, fip->ctl_src_addr);
if (fip->mode == FIP_MODE_VN2VN) {
dev_mc_del(netdev, FIP_ALL_VN2VN_MACS);
dev_mc_del(netdev, FIP_ALL_P2P_MACS);
} else
dev_mc_del(netdev, FIP_ALL_ENODE_MACS);
if (!is_zero_ether_addr(port->data_src_addr))
dev_uc_del(netdev, port->data_src_addr);
/* Tell the LLD we are done w/ FCoE */
ops = netdev->netdev_ops;
if (ops->ndo_fcoe_disable) {
if (ops->ndo_fcoe_disable(netdev))
FCOE_NETDEV_DBG(netdev, "Failed to disable FCoE"
" specific feature for LLD.\n");
}
fcoe_interface_put(fcoe);
}
/**
* fcoe_fip_recv() - Handler for received FIP frames
* @skb: The receive skb
@ -821,39 +840,9 @@ skip_oem:
* fcoe_if_destroy() - Tear down a SW FCoE instance
* @lport: The local port to be destroyed
*
* Locking: must be called with the RTNL mutex held and RTNL mutex
* needed to be dropped by this function since not dropping RTNL
* would cause circular locking warning on synchronous fip worker
* cancelling thru fcoe_interface_put invoked by this function.
*
*/
static void fcoe_if_destroy(struct fc_lport *lport)
{
struct fcoe_port *port = lport_priv(lport);
struct fcoe_interface *fcoe = port->priv;
struct net_device *netdev = fcoe->netdev;
FCOE_NETDEV_DBG(netdev, "Destroying interface\n");
/* Logout of the fabric */
fc_fabric_logoff(lport);
/* Cleanup the fc_lport */
fc_lport_destroy(lport);
/* Stop the transmit retry timer */
del_timer_sync(&port->timer);
/* Free existing transmit skbs */
fcoe_clean_pending_queue(lport);
if (!is_zero_ether_addr(port->data_src_addr))
dev_uc_del(netdev, port->data_src_addr);
rtnl_unlock();
/* receives may not be stopped until after this */
fcoe_interface_put(fcoe);
/* Free queued packets for the per-CPU receive threads */
fcoe_percpu_clean(lport);
@ -1783,23 +1772,8 @@ static int fcoe_disable(struct net_device *netdev)
int rc = 0;
mutex_lock(&fcoe_config_mutex);
#ifdef CONFIG_FCOE_MODULE
/*
* Make sure the module has been initialized, and is not about to be
* removed. Module paramter sysfs files are writable before the
* module_init function is called and after module_exit.
*/
if (THIS_MODULE->state != MODULE_STATE_LIVE) {
rc = -ENODEV;
goto out_nodev;
}
#endif
if (!rtnl_trylock()) {
mutex_unlock(&fcoe_config_mutex);
return -ERESTARTSYS;
}
rtnl_lock();
fcoe = fcoe_hostlist_lookup_port(netdev);
rtnl_unlock();
@ -1809,7 +1783,6 @@ static int fcoe_disable(struct net_device *netdev)
} else
rc = -ENODEV;
out_nodev:
mutex_unlock(&fcoe_config_mutex);
return rc;
}
@ -1828,22 +1801,7 @@ static int fcoe_enable(struct net_device *netdev)
int rc = 0;
mutex_lock(&fcoe_config_mutex);
#ifdef CONFIG_FCOE_MODULE
/*
* Make sure the module has been initialized, and is not about to be
* removed. Module paramter sysfs files are writable before the
* module_init function is called and after module_exit.
*/
if (THIS_MODULE->state != MODULE_STATE_LIVE) {
rc = -ENODEV;
goto out_nodev;
}
#endif
if (!rtnl_trylock()) {
mutex_unlock(&fcoe_config_mutex);
return -ERESTARTSYS;
}
rtnl_lock();
fcoe = fcoe_hostlist_lookup_port(netdev);
rtnl_unlock();
@ -1852,7 +1810,6 @@ static int fcoe_enable(struct net_device *netdev)
else if (!fcoe_link_ok(fcoe->ctlr.lp))
fcoe_ctlr_link_up(&fcoe->ctlr);
out_nodev:
mutex_unlock(&fcoe_config_mutex);
return rc;
}
@ -1868,35 +1825,22 @@ out_nodev:
static int fcoe_destroy(struct net_device *netdev)
{
struct fcoe_interface *fcoe;
struct fc_lport *lport;
int rc = 0;
mutex_lock(&fcoe_config_mutex);
#ifdef CONFIG_FCOE_MODULE
/*
* Make sure the module has been initialized, and is not about to be
* removed. Module paramter sysfs files are writable before the
* module_init function is called and after module_exit.
*/
if (THIS_MODULE->state != MODULE_STATE_LIVE) {
rc = -ENODEV;
goto out_nodev;
}
#endif
if (!rtnl_trylock()) {
mutex_unlock(&fcoe_config_mutex);
return -ERESTARTSYS;
}
rtnl_lock();
fcoe = fcoe_hostlist_lookup_port(netdev);
if (!fcoe) {
rtnl_unlock();
rc = -ENODEV;
goto out_nodev;
}
fcoe_interface_cleanup(fcoe);
lport = fcoe->ctlr.lp;
list_del(&fcoe->list);
/* RTNL mutex is dropped by fcoe_if_destroy */
fcoe_if_destroy(fcoe->ctlr.lp);
fcoe_interface_cleanup(fcoe);
rtnl_unlock();
fcoe_if_destroy(lport);
out_nodev:
mutex_unlock(&fcoe_config_mutex);
return rc;
@ -1912,8 +1856,6 @@ static void fcoe_destroy_work(struct work_struct *work)
port = container_of(work, struct fcoe_port, destroy_work);
mutex_lock(&fcoe_config_mutex);
rtnl_lock();
/* RTNL mutex is dropped by fcoe_if_destroy */
fcoe_if_destroy(port->lport);
mutex_unlock(&fcoe_config_mutex);
}
@ -1948,23 +1890,7 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
struct fc_lport *lport;
mutex_lock(&fcoe_config_mutex);
if (!rtnl_trylock()) {
mutex_unlock(&fcoe_config_mutex);
return -ERESTARTSYS;
}
#ifdef CONFIG_FCOE_MODULE
/*
* Make sure the module has been initialized, and is not about to be
* removed. Module paramter sysfs files are writable before the
* module_init function is called and after module_exit.
*/
if (THIS_MODULE->state != MODULE_STATE_LIVE) {
rc = -ENODEV;
goto out_nodev;
}
#endif
rtnl_lock();
/* look for existing lport */
if (fcoe_hostlist_lookup(netdev)) {

View File

@ -978,10 +978,8 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)
* the FCF that answers multicast solicitations, not the others that
* are sending periodic multicast advertisements.
*/
if (mtu_valid) {
list_del(&fcf->list);
list_add(&fcf->list, &fip->fcfs);
}
if (mtu_valid)
list_move(&fcf->list, &fip->fcfs);
/*
* If this is the first validated FCF, note the time and

View File

@ -335,7 +335,7 @@ out_attach:
EXPORT_SYMBOL(fcoe_transport_attach);
/**
* fcoe_transport_attach - Detaches an FCoE transport
* fcoe_transport_detach - Detaches an FCoE transport
* @ft: The fcoe transport to be attached
*
* Returns : 0 for success
@ -343,6 +343,7 @@ EXPORT_SYMBOL(fcoe_transport_attach);
int fcoe_transport_detach(struct fcoe_transport *ft)
{
int rc = 0;
struct fcoe_netdev_mapping *nm = NULL, *tmp;
mutex_lock(&ft_mutex);
if (!ft->attached) {
@ -352,6 +353,19 @@ int fcoe_transport_detach(struct fcoe_transport *ft)
goto out_attach;
}
/* remove netdev mapping for this transport as it is going away */
mutex_lock(&fn_mutex);
list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) {
if (nm->ft == ft) {
LIBFCOE_TRANSPORT_DBG("transport %s going away, "
"remove its netdev mapping for %s\n",
ft->name, nm->netdev->name);
list_del(&nm->list);
kfree(nm);
}
}
mutex_unlock(&fn_mutex);
list_del(&ft->list);
ft->attached = false;
LIBFCOE_TRANSPORT_DBG("detaching transport %s\n", ft->name);
@ -371,9 +385,9 @@ static int fcoe_transport_show(char *buffer, const struct kernel_param *kp)
i = j = sprintf(buffer, "Attached FCoE transports:");
mutex_lock(&ft_mutex);
list_for_each_entry(ft, &fcoe_transports, list) {
i += snprintf(&buffer[i], IFNAMSIZ, "%s ", ft->name);
if (i >= PAGE_SIZE)
if (i >= PAGE_SIZE - IFNAMSIZ)
break;
i += snprintf(&buffer[i], IFNAMSIZ, "%s ", ft->name);
}
mutex_unlock(&ft_mutex);
if (i == j)
@ -530,9 +544,6 @@ static int fcoe_transport_create(const char *buffer, struct kernel_param *kp)
struct fcoe_transport *ft = NULL;
enum fip_state fip_mode = (enum fip_state)(long)kp->arg;
if (!mutex_trylock(&ft_mutex))
return restart_syscall();
#ifdef CONFIG_LIBFCOE_MODULE
/*
* Make sure the module has been initialized, and is not about to be
@ -543,6 +554,8 @@ static int fcoe_transport_create(const char *buffer, struct kernel_param *kp)
goto out_nodev;
#endif
mutex_lock(&ft_mutex);
netdev = fcoe_if_to_netdev(buffer);
if (!netdev) {
LIBFCOE_TRANSPORT_DBG("Invalid device %s.\n", buffer);
@ -586,10 +599,7 @@ out_putdev:
dev_put(netdev);
out_nodev:
mutex_unlock(&ft_mutex);
if (rc == -ERESTARTSYS)
return restart_syscall();
else
return rc;
return rc;
}
/**
@ -608,9 +618,6 @@ static int fcoe_transport_destroy(const char *buffer, struct kernel_param *kp)
struct net_device *netdev = NULL;
struct fcoe_transport *ft = NULL;
if (!mutex_trylock(&ft_mutex))
return restart_syscall();
#ifdef CONFIG_LIBFCOE_MODULE
/*
* Make sure the module has been initialized, and is not about to be
@ -621,6 +628,8 @@ static int fcoe_transport_destroy(const char *buffer, struct kernel_param *kp)
goto out_nodev;
#endif
mutex_lock(&ft_mutex);
netdev = fcoe_if_to_netdev(buffer);
if (!netdev) {
LIBFCOE_TRANSPORT_DBG("invalid device %s.\n", buffer);
@ -645,11 +654,7 @@ out_putdev:
dev_put(netdev);
out_nodev:
mutex_unlock(&ft_mutex);
if (rc == -ERESTARTSYS)
return restart_syscall();
else
return rc;
return rc;
}
/**
@ -667,9 +672,6 @@ static int fcoe_transport_disable(const char *buffer, struct kernel_param *kp)
struct net_device *netdev = NULL;
struct fcoe_transport *ft = NULL;
if (!mutex_trylock(&ft_mutex))
return restart_syscall();
#ifdef CONFIG_LIBFCOE_MODULE
/*
* Make sure the module has been initialized, and is not about to be
@ -680,6 +682,8 @@ static int fcoe_transport_disable(const char *buffer, struct kernel_param *kp)
goto out_nodev;
#endif
mutex_lock(&ft_mutex);
netdev = fcoe_if_to_netdev(buffer);
if (!netdev)
goto out_nodev;
@ -716,9 +720,6 @@ static int fcoe_transport_enable(const char *buffer, struct kernel_param *kp)
struct net_device *netdev = NULL;
struct fcoe_transport *ft = NULL;
if (!mutex_trylock(&ft_mutex))
return restart_syscall();
#ifdef CONFIG_LIBFCOE_MODULE
/*
* Make sure the module has been initialized, and is not about to be
@ -729,6 +730,8 @@ static int fcoe_transport_enable(const char *buffer, struct kernel_param *kp)
goto out_nodev;
#endif
mutex_lock(&ft_mutex);
netdev = fcoe_if_to_netdev(buffer);
if (!netdev)
goto out_nodev;
@ -743,10 +746,7 @@ out_putdev:
dev_put(netdev);
out_nodev:
mutex_unlock(&ft_mutex);
if (rc == -ERESTARTSYS)
return restart_syscall();
else
return rc;
return rc;
}
/**

View File

@ -273,7 +273,7 @@ static ssize_t host_show_transport_mode(struct device *dev,
"performant" : "simple");
}
/* List of controllers which cannot be reset on kexec with reset_devices */
/* List of controllers which cannot be hard reset on kexec with reset_devices */
static u32 unresettable_controller[] = {
0x324a103C, /* Smart Array P712m */
0x324b103C, /* SmartArray P711m */
@ -291,16 +291,45 @@ static u32 unresettable_controller[] = {
0x409D0E11, /* Smart Array 6400 EM */
};
static int ctlr_is_resettable(struct ctlr_info *h)
/* List of controllers which cannot even be soft reset */
static u32 soft_unresettable_controller[] = {
/* Exclude 640x boards. These are two pci devices in one slot
* which share a battery backed cache module. One controls the
* cache, the other accesses the cache through the one that controls
* it. If we reset the one controlling the cache, the other will
* likely not be happy. Just forbid resetting this conjoined mess.
* The 640x isn't really supported by hpsa anyway.
*/
0x409C0E11, /* Smart Array 6400 */
0x409D0E11, /* Smart Array 6400 EM */
};
static int ctlr_is_hard_resettable(u32 board_id)
{
int i;
for (i = 0; i < ARRAY_SIZE(unresettable_controller); i++)
if (unresettable_controller[i] == h->board_id)
if (unresettable_controller[i] == board_id)
return 0;
return 1;
}
static int ctlr_is_soft_resettable(u32 board_id)
{
int i;
for (i = 0; i < ARRAY_SIZE(soft_unresettable_controller); i++)
if (soft_unresettable_controller[i] == board_id)
return 0;
return 1;
}
static int ctlr_is_resettable(u32 board_id)
{
return ctlr_is_hard_resettable(board_id) ||
ctlr_is_soft_resettable(board_id);
}
static ssize_t host_show_resettable(struct device *dev,
struct device_attribute *attr, char *buf)
{
@ -308,7 +337,7 @@ static ssize_t host_show_resettable(struct device *dev,
struct Scsi_Host *shost = class_to_shost(dev);
h = shost_to_hba(shost);
return snprintf(buf, 20, "%d\n", ctlr_is_resettable(h));
return snprintf(buf, 20, "%d\n", ctlr_is_resettable(h->board_id));
}
static inline int is_logical_dev_addr_mode(unsigned char scsi3addr[])
@ -929,13 +958,6 @@ static void hpsa_slave_destroy(struct scsi_device *sdev)
/* nothing to do. */
}
static void hpsa_scsi_setup(struct ctlr_info *h)
{
h->ndevices = 0;
h->scsi_host = NULL;
spin_lock_init(&h->devlock);
}
static void hpsa_free_sg_chain_blocks(struct ctlr_info *h)
{
int i;
@ -1006,8 +1028,7 @@ static void hpsa_unmap_sg_chain_block(struct ctlr_info *h,
pci_unmap_single(h->pdev, temp64.val, chain_sg->Len, PCI_DMA_TODEVICE);
}
static void complete_scsi_command(struct CommandList *cp,
int timeout, u32 tag)
static void complete_scsi_command(struct CommandList *cp)
{
struct scsi_cmnd *cmd;
struct ctlr_info *h;
@ -1308,7 +1329,7 @@ static void hpsa_scsi_do_simple_cmd_with_retry(struct ctlr_info *h,
int retry_count = 0;
do {
memset(c->err_info, 0, sizeof(c->err_info));
memset(c->err_info, 0, sizeof(*c->err_info));
hpsa_scsi_do_simple_cmd_core(h, c);
retry_count++;
} while (check_for_unit_attention(h, c) && retry_count <= 3);
@ -1570,6 +1591,7 @@ static unsigned char *msa2xxx_model[] = {
"MSA2024",
"MSA2312",
"MSA2324",
"P2000 G3 SAS",
NULL,
};
@ -2751,6 +2773,26 @@ static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg)
}
}
static int __devinit hpsa_send_host_reset(struct ctlr_info *h,
unsigned char *scsi3addr, u8 reset_type)
{
struct CommandList *c;
c = cmd_alloc(h);
if (!c)
return -ENOMEM;
fill_cmd(c, HPSA_DEVICE_RESET_MSG, h, NULL, 0, 0,
RAID_CTLR_LUNID, TYPE_MSG);
c->Request.CDB[1] = reset_type; /* fill_cmd defaults to target reset */
c->waiting = NULL;
enqueue_cmd_and_start_io(h, c);
/* Don't wait for completion, the reset won't complete. Don't free
* the command either. This is the last command we will send before
* re-initializing everything, so it doesn't matter and won't leak.
*/
return 0;
}
static void fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
void *buff, size_t size, u8 page_code, unsigned char *scsi3addr,
int cmd_type)
@ -2828,7 +2870,8 @@ static void fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
c->Request.Type.Attribute = ATTR_SIMPLE;
c->Request.Type.Direction = XFER_NONE;
c->Request.Timeout = 0; /* Don't time out */
c->Request.CDB[0] = 0x01; /* RESET_MSG is 0x01 */
memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB));
c->Request.CDB[0] = cmd;
c->Request.CDB[1] = 0x03; /* Reset target above */
/* If bytes 4-7 are zero, it means reset the */
/* LunID device */
@ -2936,7 +2979,7 @@ static inline void finish_cmd(struct CommandList *c, u32 raw_tag)
{
removeQ(c);
if (likely(c->cmd_type == CMD_SCSI))
complete_scsi_command(c, 0, raw_tag);
complete_scsi_command(c);
else if (c->cmd_type == CMD_IOCTL_PEND)
complete(c->waiting);
}
@ -2994,6 +3037,63 @@ static inline u32 process_nonindexed_cmd(struct ctlr_info *h,
return next_command(h);
}
/* Some controllers, like p400, will give us one interrupt
* after a soft reset, even if we turned interrupts off.
* Only need to check for this in the hpsa_xxx_discard_completions
* functions.
*/
static int ignore_bogus_interrupt(struct ctlr_info *h)
{
if (likely(!reset_devices))
return 0;
if (likely(h->interrupts_enabled))
return 0;
dev_info(&h->pdev->dev, "Received interrupt while interrupts disabled "
"(known firmware bug.) Ignoring.\n");
return 1;
}
static irqreturn_t hpsa_intx_discard_completions(int irq, void *dev_id)
{
struct ctlr_info *h = dev_id;
unsigned long flags;
u32 raw_tag;
if (ignore_bogus_interrupt(h))
return IRQ_NONE;
if (interrupt_not_for_us(h))
return IRQ_NONE;
spin_lock_irqsave(&h->lock, flags);
while (interrupt_pending(h)) {
raw_tag = get_next_completion(h);
while (raw_tag != FIFO_EMPTY)
raw_tag = next_command(h);
}
spin_unlock_irqrestore(&h->lock, flags);
return IRQ_HANDLED;
}
static irqreturn_t hpsa_msix_discard_completions(int irq, void *dev_id)
{
struct ctlr_info *h = dev_id;
unsigned long flags;
u32 raw_tag;
if (ignore_bogus_interrupt(h))
return IRQ_NONE;
spin_lock_irqsave(&h->lock, flags);
raw_tag = get_next_completion(h);
while (raw_tag != FIFO_EMPTY)
raw_tag = next_command(h);
spin_unlock_irqrestore(&h->lock, flags);
return IRQ_HANDLED;
}
static irqreturn_t do_hpsa_intr_intx(int irq, void *dev_id)
{
struct ctlr_info *h = dev_id;
@ -3132,11 +3232,10 @@ static __devinit int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
return 0;
}
#define hpsa_soft_reset_controller(p) hpsa_message(p, 1, 0)
#define hpsa_noop(p) hpsa_message(p, 3, 0)
static int hpsa_controller_hard_reset(struct pci_dev *pdev,
void * __iomem vaddr, bool use_doorbell)
void * __iomem vaddr, u32 use_doorbell)
{
u16 pmcsr;
int pos;
@ -3147,8 +3246,7 @@ static int hpsa_controller_hard_reset(struct pci_dev *pdev,
* other way using the doorbell register.
*/
dev_info(&pdev->dev, "using doorbell to reset controller\n");
writel(DOORBELL_CTLR_RESET, vaddr + SA5_DOORBELL);
msleep(1000);
writel(use_doorbell, vaddr + SA5_DOORBELL);
} else { /* Try to do it the PCI power state way */
/* Quoting from the Open CISS Specification: "The Power
@ -3179,12 +3277,63 @@ static int hpsa_controller_hard_reset(struct pci_dev *pdev,
pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
pmcsr |= PCI_D0;
pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
msleep(500);
}
return 0;
}
static __devinit void init_driver_version(char *driver_version, int len)
{
memset(driver_version, 0, len);
strncpy(driver_version, "hpsa " HPSA_DRIVER_VERSION, len - 1);
}
static __devinit int write_driver_ver_to_cfgtable(
struct CfgTable __iomem *cfgtable)
{
char *driver_version;
int i, size = sizeof(cfgtable->driver_version);
driver_version = kmalloc(size, GFP_KERNEL);
if (!driver_version)
return -ENOMEM;
init_driver_version(driver_version, size);
for (i = 0; i < size; i++)
writeb(driver_version[i], &cfgtable->driver_version[i]);
kfree(driver_version);
return 0;
}
static __devinit void read_driver_ver_from_cfgtable(
struct CfgTable __iomem *cfgtable, unsigned char *driver_ver)
{
int i;
for (i = 0; i < sizeof(cfgtable->driver_version); i++)
driver_ver[i] = readb(&cfgtable->driver_version[i]);
}
static __devinit int controller_reset_failed(
struct CfgTable __iomem *cfgtable)
{
char *driver_ver, *old_driver_ver;
int rc, size = sizeof(cfgtable->driver_version);
old_driver_ver = kmalloc(2 * size, GFP_KERNEL);
if (!old_driver_ver)
return -ENOMEM;
driver_ver = old_driver_ver + size;
/* After a reset, the 32 bytes of "driver version" in the cfgtable
* should have been changed, otherwise we know the reset failed.
*/
init_driver_version(old_driver_ver, size);
read_driver_ver_from_cfgtable(cfgtable, driver_ver);
rc = !memcmp(driver_ver, old_driver_ver, size);
kfree(old_driver_ver);
return rc;
}
/* This does a hard reset of the controller using PCI power management
* states or the using the doorbell register.
*/
@ -3195,10 +3344,10 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
u64 cfg_base_addr_index;
void __iomem *vaddr;
unsigned long paddr;
u32 misc_fw_support, active_transport;
u32 misc_fw_support;
int rc;
struct CfgTable __iomem *cfgtable;
bool use_doorbell;
u32 use_doorbell;
u32 board_id;
u16 command_register;
@ -3215,20 +3364,15 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
* using the doorbell register.
*/
/* Exclude 640x boards. These are two pci devices in one slot
* which share a battery backed cache module. One controls the
* cache, the other accesses the cache through the one that controls
* it. If we reset the one controlling the cache, the other will
* likely not be happy. Just forbid resetting this conjoined mess.
* The 640x isn't really supported by hpsa anyway.
*/
rc = hpsa_lookup_board_id(pdev, &board_id);
if (rc < 0) {
if (rc < 0 || !ctlr_is_resettable(board_id)) {
dev_warn(&pdev->dev, "Not resetting device.\n");
return -ENODEV;
}
if (board_id == 0x409C0E11 || board_id == 0x409D0E11)
return -ENOTSUPP;
/* if controller is soft- but not hard resettable... */
if (!ctlr_is_hard_resettable(board_id))
return -ENOTSUPP; /* try soft reset later. */
/* Save the PCI command register */
pci_read_config_word(pdev, 4, &command_register);
@ -3257,10 +3401,28 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
rc = -ENOMEM;
goto unmap_vaddr;
}
rc = write_driver_ver_to_cfgtable(cfgtable);
if (rc)
goto unmap_vaddr;
/* If reset via doorbell register is supported, use that. */
/* If reset via doorbell register is supported, use that.
* There are two such methods. Favor the newest method.
*/
misc_fw_support = readl(&cfgtable->misc_fw_support);
use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET;
use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET2;
if (use_doorbell) {
use_doorbell = DOORBELL_CTLR_RESET2;
} else {
use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET;
if (use_doorbell) {
dev_warn(&pdev->dev, "Controller claims that "
"'Bit 2 doorbell reset' is "
"supported, but not 'bit 5 doorbell reset'. "
"Firmware update is recommended.\n");
rc = -ENOTSUPP; /* try soft reset */
goto unmap_cfgtable;
}
}
rc = hpsa_controller_hard_reset(pdev, vaddr, use_doorbell);
if (rc)
@ -3279,30 +3441,32 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
msleep(HPSA_POST_RESET_PAUSE_MSECS);
/* Wait for board to become not ready, then ready. */
dev_info(&pdev->dev, "Waiting for board to become ready.\n");
dev_info(&pdev->dev, "Waiting for board to reset.\n");
rc = hpsa_wait_for_board_state(pdev, vaddr, BOARD_NOT_READY);
if (rc)
if (rc) {
dev_warn(&pdev->dev,
"failed waiting for board to become not ready\n");
"failed waiting for board to reset."
" Will try soft reset.\n");
rc = -ENOTSUPP; /* Not expected, but try soft reset later */
goto unmap_cfgtable;
}
rc = hpsa_wait_for_board_state(pdev, vaddr, BOARD_READY);
if (rc) {
dev_warn(&pdev->dev,
"failed waiting for board to become ready\n");
"failed waiting for board to become ready "
"after hard reset\n");
goto unmap_cfgtable;
}
dev_info(&pdev->dev, "board ready.\n");
/* Controller should be in simple mode at this point. If it's not,
* It means we're on one of those controllers which doesn't support
* the doorbell reset method and on which the PCI power management reset
* method doesn't work (P800, for example.)
* In those cases, don't try to proceed, as it generally doesn't work.
*/
active_transport = readl(&cfgtable->TransportActive);
if (active_transport & PERFORMANT_MODE) {
dev_warn(&pdev->dev, "Unable to successfully reset controller,"
" Ignoring controller.\n");
rc = -ENODEV;
rc = controller_reset_failed(vaddr);
if (rc < 0)
goto unmap_cfgtable;
if (rc) {
dev_warn(&pdev->dev, "Unable to successfully reset "
"controller. Will try soft reset.\n");
rc = -ENOTSUPP;
} else {
dev_info(&pdev->dev, "board ready after hard reset.\n");
}
unmap_cfgtable:
@ -3543,6 +3707,9 @@ static int __devinit hpsa_find_cfgtables(struct ctlr_info *h)
cfg_base_addr_index) + cfg_offset, sizeof(*h->cfgtable));
if (!h->cfgtable)
return -ENOMEM;
rc = write_driver_ver_to_cfgtable(h->cfgtable);
if (rc)
return rc;
/* Find performant mode table. */
trans_offset = readl(&h->cfgtable->TransMethodOffset);
h->transtable = remap_pci_mem(pci_resource_start(h->pdev,
@ -3777,11 +3944,12 @@ static __devinit int hpsa_init_reset_devices(struct pci_dev *pdev)
* due to concerns about shared bbwc between 6402/6404 pair.
*/
if (rc == -ENOTSUPP)
return 0; /* just try to do the kdump anyhow. */
return rc; /* just try to do the kdump anyhow. */
if (rc)
return -ENODEV;
/* Now try to get the controller to respond to a no-op */
dev_warn(&pdev->dev, "Waiting for controller to respond to no-op\n");
for (i = 0; i < HPSA_POST_RESET_NOOP_RETRIES; i++) {
if (hpsa_noop(pdev) == 0)
break;
@ -3792,18 +3960,133 @@ static __devinit int hpsa_init_reset_devices(struct pci_dev *pdev)
return 0;
}
static __devinit int hpsa_allocate_cmd_pool(struct ctlr_info *h)
{
h->cmd_pool_bits = kzalloc(
DIV_ROUND_UP(h->nr_cmds, BITS_PER_LONG) *
sizeof(unsigned long), GFP_KERNEL);
h->cmd_pool = pci_alloc_consistent(h->pdev,
h->nr_cmds * sizeof(*h->cmd_pool),
&(h->cmd_pool_dhandle));
h->errinfo_pool = pci_alloc_consistent(h->pdev,
h->nr_cmds * sizeof(*h->errinfo_pool),
&(h->errinfo_pool_dhandle));
if ((h->cmd_pool_bits == NULL)
|| (h->cmd_pool == NULL)
|| (h->errinfo_pool == NULL)) {
dev_err(&h->pdev->dev, "out of memory in %s", __func__);
return -ENOMEM;
}
return 0;
}
static void hpsa_free_cmd_pool(struct ctlr_info *h)
{
kfree(h->cmd_pool_bits);
if (h->cmd_pool)
pci_free_consistent(h->pdev,
h->nr_cmds * sizeof(struct CommandList),
h->cmd_pool, h->cmd_pool_dhandle);
if (h->errinfo_pool)
pci_free_consistent(h->pdev,
h->nr_cmds * sizeof(struct ErrorInfo),
h->errinfo_pool,
h->errinfo_pool_dhandle);
}
static int hpsa_request_irq(struct ctlr_info *h,
irqreturn_t (*msixhandler)(int, void *),
irqreturn_t (*intxhandler)(int, void *))
{
int rc;
if (h->msix_vector || h->msi_vector)
rc = request_irq(h->intr[h->intr_mode], msixhandler,
IRQF_DISABLED, h->devname, h);
else
rc = request_irq(h->intr[h->intr_mode], intxhandler,
IRQF_DISABLED, h->devname, h);
if (rc) {
dev_err(&h->pdev->dev, "unable to get irq %d for %s\n",
h->intr[h->intr_mode], h->devname);
return -ENODEV;
}
return 0;
}
static int __devinit hpsa_kdump_soft_reset(struct ctlr_info *h)
{
if (hpsa_send_host_reset(h, RAID_CTLR_LUNID,
HPSA_RESET_TYPE_CONTROLLER)) {
dev_warn(&h->pdev->dev, "Resetting array controller failed.\n");
return -EIO;
}
dev_info(&h->pdev->dev, "Waiting for board to soft reset.\n");
if (hpsa_wait_for_board_state(h->pdev, h->vaddr, BOARD_NOT_READY)) {
dev_warn(&h->pdev->dev, "Soft reset had no effect.\n");
return -1;
}
dev_info(&h->pdev->dev, "Board reset, awaiting READY status.\n");
if (hpsa_wait_for_board_state(h->pdev, h->vaddr, BOARD_READY)) {
dev_warn(&h->pdev->dev, "Board failed to become ready "
"after soft reset.\n");
return -1;
}
return 0;
}
static void hpsa_undo_allocations_after_kdump_soft_reset(struct ctlr_info *h)
{
free_irq(h->intr[h->intr_mode], h);
#ifdef CONFIG_PCI_MSI
if (h->msix_vector)
pci_disable_msix(h->pdev);
else if (h->msi_vector)
pci_disable_msi(h->pdev);
#endif /* CONFIG_PCI_MSI */
hpsa_free_sg_chain_blocks(h);
hpsa_free_cmd_pool(h);
kfree(h->blockFetchTable);
pci_free_consistent(h->pdev, h->reply_pool_size,
h->reply_pool, h->reply_pool_dhandle);
if (h->vaddr)
iounmap(h->vaddr);
if (h->transtable)
iounmap(h->transtable);
if (h->cfgtable)
iounmap(h->cfgtable);
pci_release_regions(h->pdev);
kfree(h);
}
static int __devinit hpsa_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int dac, rc;
struct ctlr_info *h;
int try_soft_reset = 0;
unsigned long flags;
if (number_of_controllers == 0)
printk(KERN_INFO DRIVER_NAME "\n");
rc = hpsa_init_reset_devices(pdev);
if (rc)
return rc;
if (rc) {
if (rc != -ENOTSUPP)
return rc;
/* If the reset fails in a particular way (it has no way to do
* a proper hard reset, so returns -ENOTSUPP) we can try to do
* a soft reset once we get the controller configured up to the
* point that it can accept a command.
*/
try_soft_reset = 1;
rc = 0;
}
reinit_after_soft_reset:
/* Command structures must be aligned on a 32-byte boundary because
* the 5 lower bits of the address are used by the hardware. and by
@ -3847,54 +4130,82 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,
/* make sure the board interrupts are off */
h->access.set_intr_mask(h, HPSA_INTR_OFF);
if (h->msix_vector || h->msi_vector)
rc = request_irq(h->intr[h->intr_mode], do_hpsa_intr_msi,
IRQF_DISABLED, h->devname, h);
else
rc = request_irq(h->intr[h->intr_mode], do_hpsa_intr_intx,
IRQF_DISABLED, h->devname, h);
if (rc) {
dev_err(&pdev->dev, "unable to get irq %d for %s\n",
h->intr[h->intr_mode], h->devname);
if (hpsa_request_irq(h, do_hpsa_intr_msi, do_hpsa_intr_intx))
goto clean2;
}
dev_info(&pdev->dev, "%s: <0x%x> at IRQ %d%s using DAC\n",
h->devname, pdev->device,
h->intr[h->intr_mode], dac ? "" : " not");
h->cmd_pool_bits =
kmalloc(((h->nr_cmds + BITS_PER_LONG -
1) / BITS_PER_LONG) * sizeof(unsigned long), GFP_KERNEL);
h->cmd_pool = pci_alloc_consistent(h->pdev,
h->nr_cmds * sizeof(*h->cmd_pool),
&(h->cmd_pool_dhandle));
h->errinfo_pool = pci_alloc_consistent(h->pdev,
h->nr_cmds * sizeof(*h->errinfo_pool),
&(h->errinfo_pool_dhandle));
if ((h->cmd_pool_bits == NULL)
|| (h->cmd_pool == NULL)
|| (h->errinfo_pool == NULL)) {
dev_err(&pdev->dev, "out of memory");
rc = -ENOMEM;
if (hpsa_allocate_cmd_pool(h))
goto clean4;
}
if (hpsa_allocate_sg_chain_blocks(h))
goto clean4;
init_waitqueue_head(&h->scan_wait_queue);
h->scan_finished = 1; /* no scan currently in progress */
pci_set_drvdata(pdev, h);
memset(h->cmd_pool_bits, 0,
((h->nr_cmds + BITS_PER_LONG -
1) / BITS_PER_LONG) * sizeof(unsigned long));
h->ndevices = 0;
h->scsi_host = NULL;
spin_lock_init(&h->devlock);
hpsa_put_ctlr_into_performant_mode(h);
hpsa_scsi_setup(h);
/* At this point, the controller is ready to take commands.
* Now, if reset_devices and the hard reset didn't work, try
* the soft reset and see if that works.
*/
if (try_soft_reset) {
/* This is kind of gross. We may or may not get a completion
* from the soft reset command, and if we do, then the value
* from the fifo may or may not be valid. So, we wait 10 secs
* after the reset throwing away any completions we get during
* that time. Unregister the interrupt handler and register
* fake ones to scoop up any residual completions.
*/
spin_lock_irqsave(&h->lock, flags);
h->access.set_intr_mask(h, HPSA_INTR_OFF);
spin_unlock_irqrestore(&h->lock, flags);
free_irq(h->intr[h->intr_mode], h);
rc = hpsa_request_irq(h, hpsa_msix_discard_completions,
hpsa_intx_discard_completions);
if (rc) {
dev_warn(&h->pdev->dev, "Failed to request_irq after "
"soft reset.\n");
goto clean4;
}
rc = hpsa_kdump_soft_reset(h);
if (rc)
/* Neither hard nor soft reset worked, we're hosed. */
goto clean4;
dev_info(&h->pdev->dev, "Board READY.\n");
dev_info(&h->pdev->dev,
"Waiting for stale completions to drain.\n");
h->access.set_intr_mask(h, HPSA_INTR_ON);
msleep(10000);
h->access.set_intr_mask(h, HPSA_INTR_OFF);
rc = controller_reset_failed(h->cfgtable);
if (rc)
dev_info(&h->pdev->dev,
"Soft reset appears to have failed.\n");
/* since the controller's reset, we have to go back and re-init
* everything. Easiest to just forget what we've done and do it
* all over again.
*/
hpsa_undo_allocations_after_kdump_soft_reset(h);
try_soft_reset = 0;
if (rc)
/* don't go to clean4, we already unallocated */
return -ENODEV;
goto reinit_after_soft_reset;
}
/* Turn the interrupts on so we can service requests */
h->access.set_intr_mask(h, HPSA_INTR_ON);
hpsa_put_ctlr_into_performant_mode(h);
hpsa_hba_inquiry(h);
hpsa_register_scsi(h); /* hook ourselves into SCSI subsystem */
h->busy_initializing = 0;
@ -3902,16 +4213,7 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,
clean4:
hpsa_free_sg_chain_blocks(h);
kfree(h->cmd_pool_bits);
if (h->cmd_pool)
pci_free_consistent(h->pdev,
h->nr_cmds * sizeof(struct CommandList),
h->cmd_pool, h->cmd_pool_dhandle);
if (h->errinfo_pool)
pci_free_consistent(h->pdev,
h->nr_cmds * sizeof(struct ErrorInfo),
h->errinfo_pool,
h->errinfo_pool_dhandle);
hpsa_free_cmd_pool(h);
free_irq(h->intr[h->intr_mode], h);
clean2:
clean1:

View File

@ -127,10 +127,12 @@ struct ctlr_info {
};
#define HPSA_ABORT_MSG 0
#define HPSA_DEVICE_RESET_MSG 1
#define HPSA_BUS_RESET_MSG 2
#define HPSA_HOST_RESET_MSG 3
#define HPSA_RESET_TYPE_CONTROLLER 0x00
#define HPSA_RESET_TYPE_BUS 0x01
#define HPSA_RESET_TYPE_TARGET 0x03
#define HPSA_RESET_TYPE_LUN 0x04
#define HPSA_MSG_SEND_RETRY_LIMIT 10
#define HPSA_MSG_SEND_RETRY_INTERVAL_MSECS 1000
#define HPSA_MSG_SEND_RETRY_INTERVAL_MSECS (10000)
/* Maximum time in seconds driver will wait for command completions
* when polling before giving up.
@ -155,7 +157,7 @@ struct ctlr_info {
* HPSA_BOARD_READY_ITERATIONS are derived from those.
*/
#define HPSA_BOARD_READY_WAIT_SECS (120)
#define HPSA_BOARD_NOT_READY_WAIT_SECS (10)
#define HPSA_BOARD_NOT_READY_WAIT_SECS (100)
#define HPSA_BOARD_READY_POLL_INTERVAL_MSECS (100)
#define HPSA_BOARD_READY_POLL_INTERVAL \
((HPSA_BOARD_READY_POLL_INTERVAL_MSECS * HZ) / 1000)
@ -212,6 +214,7 @@ static void SA5_submit_command(struct ctlr_info *h,
dev_dbg(&h->pdev->dev, "Sending %x, tag = %x\n", c->busaddr,
c->Header.Tag.lower);
writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
(void) readl(h->vaddr + SA5_REQUEST_PORT_OFFSET);
h->commands_outstanding++;
if (h->commands_outstanding > h->max_outstanding)
h->max_outstanding = h->commands_outstanding;
@ -227,10 +230,12 @@ static void SA5_intr_mask(struct ctlr_info *h, unsigned long val)
if (val) { /* Turn interrupts on */
h->interrupts_enabled = 1;
writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
(void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
} else { /* Turn them off */
h->interrupts_enabled = 0;
writel(SA5_INTR_OFF,
h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
(void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
}
}
@ -239,10 +244,12 @@ static void SA5_performant_intr_mask(struct ctlr_info *h, unsigned long val)
if (val) { /* turn on interrupts */
h->interrupts_enabled = 1;
writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
(void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
} else {
h->interrupts_enabled = 0;
writel(SA5_PERF_INTR_OFF,
h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
(void) readl(h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
}
}

View File

@ -101,6 +101,7 @@
#define CFGTBL_ChangeReq 0x00000001l
#define CFGTBL_AccCmds 0x00000001l
#define DOORBELL_CTLR_RESET 0x00000004l
#define DOORBELL_CTLR_RESET2 0x00000020l
#define CFGTBL_Trans_Simple 0x00000002l
#define CFGTBL_Trans_Performant 0x00000004l
@ -256,14 +257,6 @@ struct ErrorInfo {
#define CMD_IOCTL_PEND 0x01
#define CMD_SCSI 0x03
/* This structure needs to be divisible by 32 for new
* indexing method and performant mode.
*/
#define PAD32 32
#define PAD64DIFF 0
#define USEEXTRA ((sizeof(void *) - 4)/4)
#define PADSIZE (PAD32 + PAD64DIFF * USEEXTRA)
#define DIRECT_LOOKUP_SHIFT 5
#define DIRECT_LOOKUP_BIT 0x10
#define DIRECT_LOOKUP_MASK (~((1 << DIRECT_LOOKUP_SHIFT) - 1))
@ -345,6 +338,8 @@ struct CfgTable {
u8 reserved[0x78 - 0x58];
u32 misc_fw_support; /* offset 0x78 */
#define MISC_FW_DOORBELL_RESET (0x02)
#define MISC_FW_DOORBELL_RESET2 (0x010)
u8 driver_version[32];
};
#define NUM_BLOCKFETCH_ENTRIES 8

View File

@ -1849,8 +1849,7 @@ static void ibmvscsi_do_work(struct ibmvscsi_host_data *hostdata)
rc = ibmvscsi_ops->reset_crq_queue(&hostdata->queue, hostdata);
if (!rc)
rc = ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0);
if (!rc)
rc = vio_enable_interrupts(to_vio_dev(hostdata->dev));
vio_enable_interrupts(to_vio_dev(hostdata->dev));
} else if (hostdata->reenable_crq) {
smp_rmb();
action = "enable";

View File

@ -343,7 +343,7 @@ static int in2000_queuecommand_lck(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
instance = cmd->device->host;
hostdata = (struct IN2000_hostdata *) instance->hostdata;
DB(DB_QUEUE_COMMAND, scmd_printk(KERN_DEBUG, cmd, "Q-%02x-%ld(", cmd->cmnd[0], cmd->serial_number))
DB(DB_QUEUE_COMMAND, scmd_printk(KERN_DEBUG, cmd, "Q-%02x(", cmd->cmnd[0]))
/* Set up a few fields in the Scsi_Cmnd structure for our own use:
* - host_scribble is the pointer to the next cmd in the input queue
@ -427,7 +427,7 @@ static int in2000_queuecommand_lck(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
in2000_execute(cmd->device->host);
DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->serial_number))
DB(DB_QUEUE_COMMAND, printk(")Q "))
return 0;
}
@ -705,7 +705,7 @@ static void in2000_execute(struct Scsi_Host *instance)
* to search the input_Q again...
*/
DB(DB_EXECUTE, printk("%s%ld)EX-2 ", (cmd->SCp.phase) ? "d:" : "", cmd->serial_number))
DB(DB_EXECUTE, printk("%s)EX-2 ", (cmd->SCp.phase) ? "d:" : ""))
}
@ -1149,7 +1149,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id)
case CSR_XFER_DONE | PHS_COMMAND:
case CSR_UNEXP | PHS_COMMAND:
case CSR_SRV_REQ | PHS_COMMAND:
DB(DB_INTR, printk("CMND-%02x,%ld", cmd->cmnd[0], cmd->serial_number))
DB(DB_INTR, printk("CMND-%02x", cmd->cmnd[0]))
transfer_pio(cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR, hostdata);
hostdata->state = S_CONNECTED;
break;
@ -1191,7 +1191,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id)
switch (msg) {
case COMMAND_COMPLETE:
DB(DB_INTR, printk("CCMP-%ld", cmd->serial_number))
DB(DB_INTR, printk("CCMP"))
write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
hostdata->state = S_PRE_CMP_DISC;
break;
@ -1329,7 +1329,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id)
write_3393(hostdata, WD_SOURCE_ID, SRCID_ER);
if (phs == 0x60) {
DB(DB_INTR, printk("SX-DONE-%ld", cmd->serial_number))
DB(DB_INTR, printk("SX-DONE"))
cmd->SCp.Message = COMMAND_COMPLETE;
lun = read_3393(hostdata, WD_TARGET_LUN);
DB(DB_INTR, printk(":%d.%d", cmd->SCp.Status, lun))
@ -1350,7 +1350,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id)
in2000_execute(instance);
} else {
printk("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---", asr, sr, phs, cmd->serial_number);
printk("%02x:%02x:%02x: Unknown SEL_XFER_DONE phase!!---", asr, sr, phs);
}
break;
@ -1417,7 +1417,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id)
spin_unlock_irqrestore(instance->host_lock, flags);
return IRQ_HANDLED;
}
DB(DB_INTR, printk("UNEXP_DISC-%ld", cmd->serial_number))
DB(DB_INTR, printk("UNEXP_DISC"))
hostdata->connected = NULL;
hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
hostdata->state = S_UNCONNECTED;
@ -1442,7 +1442,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id)
*/
write_3393(hostdata, WD_SOURCE_ID, SRCID_ER);
DB(DB_INTR, printk("DISC-%ld", cmd->serial_number))
DB(DB_INTR, printk("DISC"))
if (cmd == NULL) {
printk(" - Already disconnected! ");
hostdata->state = S_UNCONNECTED;
@ -1575,7 +1575,6 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id)
} else
hostdata->state = S_CONNECTED;
DB(DB_INTR, printk("-%ld", cmd->serial_number))
break;
default:
@ -1704,7 +1703,7 @@ static int __in2000_abort(Scsi_Cmnd * cmd)
prev->host_scribble = cmd->host_scribble;
cmd->host_scribble = NULL;
cmd->result = DID_ABORT << 16;
printk(KERN_WARNING "scsi%d: Abort - removing command %ld from input_Q. ", instance->host_no, cmd->serial_number);
printk(KERN_WARNING "scsi%d: Abort - removing command from input_Q. ", instance->host_no);
cmd->scsi_done(cmd);
return SUCCESS;
}
@ -1725,7 +1724,7 @@ static int __in2000_abort(Scsi_Cmnd * cmd)
if (hostdata->connected == cmd) {
printk(KERN_WARNING "scsi%d: Aborting connected command %ld - ", instance->host_no, cmd->serial_number);
printk(KERN_WARNING "scsi%d: Aborting connected command - ", instance->host_no);
printk("sending wd33c93 ABORT command - ");
write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
@ -2270,7 +2269,7 @@ static int in2000_proc_info(struct Scsi_Host *instance, char *buf, char **start,
strcat(bp, "\nconnected: ");
if (hd->connected) {
cmd = (Scsi_Cmnd *) hd->connected;
sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
sprintf(tbuf, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
strcat(bp, tbuf);
}
}
@ -2278,7 +2277,7 @@ static int in2000_proc_info(struct Scsi_Host *instance, char *buf, char **start,
strcat(bp, "\ninput_Q: ");
cmd = (Scsi_Cmnd *) hd->input_Q;
while (cmd) {
sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
sprintf(tbuf, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
strcat(bp, tbuf);
cmd = (Scsi_Cmnd *) cmd->host_scribble;
}
@ -2287,7 +2286,7 @@ static int in2000_proc_info(struct Scsi_Host *instance, char *buf, char **start,
strcat(bp, "\ndisconnected_Q:");
cmd = (Scsi_Cmnd *) hd->disconnected_Q;
while (cmd) {
sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
sprintf(tbuf, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
strcat(bp, tbuf);
cmd = (Scsi_Cmnd *) cmd->host_scribble;
}

View File

@ -60,6 +60,7 @@
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/pci.h>
@ -2717,13 +2718,18 @@ static int ipr_sdt_copy(struct ipr_ioa_cfg *ioa_cfg,
unsigned long pci_address, u32 length)
{
int bytes_copied = 0;
int cur_len, rc, rem_len, rem_page_len;
int cur_len, rc, rem_len, rem_page_len, max_dump_size;
__be32 *page;
unsigned long lock_flags = 0;
struct ipr_ioa_dump *ioa_dump = &ioa_cfg->dump->ioa_dump;
if (ioa_cfg->sis64)
max_dump_size = IPR_FMT3_MAX_IOA_DUMP_SIZE;
else
max_dump_size = IPR_FMT2_MAX_IOA_DUMP_SIZE;
while (bytes_copied < length &&
(ioa_dump->hdr.len + bytes_copied) < IPR_MAX_IOA_DUMP_SIZE) {
(ioa_dump->hdr.len + bytes_copied) < max_dump_size) {
if (ioa_dump->page_offset >= PAGE_SIZE ||
ioa_dump->page_offset == 0) {
page = (__be32 *)__get_free_page(GFP_ATOMIC);
@ -2885,8 +2891,8 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump)
unsigned long lock_flags = 0;
struct ipr_driver_dump *driver_dump = &dump->driver_dump;
struct ipr_ioa_dump *ioa_dump = &dump->ioa_dump;
u32 num_entries, start_off, end_off;
u32 bytes_to_copy, bytes_copied, rc;
u32 num_entries, max_num_entries, start_off, end_off;
u32 max_dump_size, bytes_to_copy, bytes_copied, rc;
struct ipr_sdt *sdt;
int valid = 1;
int i;
@ -2947,8 +2953,18 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump)
on entries in this table */
sdt = &ioa_dump->sdt;
if (ioa_cfg->sis64) {
max_num_entries = IPR_FMT3_NUM_SDT_ENTRIES;
max_dump_size = IPR_FMT3_MAX_IOA_DUMP_SIZE;
} else {
max_num_entries = IPR_FMT2_NUM_SDT_ENTRIES;
max_dump_size = IPR_FMT2_MAX_IOA_DUMP_SIZE;
}
bytes_to_copy = offsetof(struct ipr_sdt, entry) +
(max_num_entries * sizeof(struct ipr_sdt_entry));
rc = ipr_get_ldump_data_section(ioa_cfg, start_addr, (__be32 *)sdt,
sizeof(struct ipr_sdt) / sizeof(__be32));
bytes_to_copy / sizeof(__be32));
/* Smart Dump table is ready to use and the first entry is valid */
if (rc || ((be32_to_cpu(sdt->hdr.state) != IPR_FMT3_SDT_READY_TO_USE) &&
@ -2964,13 +2980,20 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump)
num_entries = be32_to_cpu(sdt->hdr.num_entries_used);
if (num_entries > IPR_NUM_SDT_ENTRIES)
num_entries = IPR_NUM_SDT_ENTRIES;
if (num_entries > max_num_entries)
num_entries = max_num_entries;
/* Update dump length to the actual data to be copied */
dump->driver_dump.hdr.len += sizeof(struct ipr_sdt_header);
if (ioa_cfg->sis64)
dump->driver_dump.hdr.len += num_entries * sizeof(struct ipr_sdt_entry);
else
dump->driver_dump.hdr.len += max_num_entries * sizeof(struct ipr_sdt_entry);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
for (i = 0; i < num_entries; i++) {
if (ioa_dump->hdr.len > IPR_MAX_IOA_DUMP_SIZE) {
if (ioa_dump->hdr.len > max_dump_size) {
driver_dump->hdr.status = IPR_DUMP_STATUS_QUAL_SUCCESS;
break;
}
@ -2989,7 +3012,7 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump)
valid = 0;
}
if (valid) {
if (bytes_to_copy > IPR_MAX_IOA_DUMP_SIZE) {
if (bytes_to_copy > max_dump_size) {
sdt->entry[i].flags &= ~IPR_SDT_VALID_ENTRY;
continue;
}
@ -3044,6 +3067,7 @@ static void ipr_release_dump(struct kref *kref)
for (i = 0; i < dump->ioa_dump.next_page_index; i++)
free_page((unsigned long) dump->ioa_dump.ioa_data[i]);
vfree(dump->ioa_dump.ioa_data);
kfree(dump);
LEAVE;
}
@ -3835,7 +3859,7 @@ static ssize_t ipr_read_dump(struct file *filp, struct kobject *kobj,
struct ipr_dump *dump;
unsigned long lock_flags = 0;
char *src;
int len;
int len, sdt_end;
size_t rc = count;
if (!capable(CAP_SYS_ADMIN))
@ -3875,9 +3899,17 @@ static ssize_t ipr_read_dump(struct file *filp, struct kobject *kobj,
off -= sizeof(dump->driver_dump);
if (count && off < offsetof(struct ipr_ioa_dump, ioa_data)) {
if (off + count > offsetof(struct ipr_ioa_dump, ioa_data))
len = offsetof(struct ipr_ioa_dump, ioa_data) - off;
if (ioa_cfg->sis64)
sdt_end = offsetof(struct ipr_ioa_dump, sdt.entry) +
(be32_to_cpu(dump->ioa_dump.sdt.hdr.num_entries_used) *
sizeof(struct ipr_sdt_entry));
else
sdt_end = offsetof(struct ipr_ioa_dump, sdt.entry) +
(IPR_FMT2_NUM_SDT_ENTRIES * sizeof(struct ipr_sdt_entry));
if (count && off < sdt_end) {
if (off + count > sdt_end)
len = sdt_end - off;
else
len = count;
src = (u8 *)&dump->ioa_dump + off;
@ -3887,7 +3919,7 @@ static ssize_t ipr_read_dump(struct file *filp, struct kobject *kobj,
count -= len;
}
off -= offsetof(struct ipr_ioa_dump, ioa_data);
off -= sdt_end;
while (count) {
if ((off & PAGE_MASK) != ((off + count) & PAGE_MASK))
@ -3916,6 +3948,7 @@ static ssize_t ipr_read_dump(struct file *filp, struct kobject *kobj,
static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg)
{
struct ipr_dump *dump;
__be32 **ioa_data;
unsigned long lock_flags = 0;
dump = kzalloc(sizeof(struct ipr_dump), GFP_KERNEL);
@ -3925,6 +3958,19 @@ static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg)
return -ENOMEM;
}
if (ioa_cfg->sis64)
ioa_data = vmalloc(IPR_FMT3_MAX_NUM_DUMP_PAGES * sizeof(__be32 *));
else
ioa_data = vmalloc(IPR_FMT2_MAX_NUM_DUMP_PAGES * sizeof(__be32 *));
if (!ioa_data) {
ipr_err("Dump memory allocation failed\n");
kfree(dump);
return -ENOMEM;
}
dump->ioa_dump.ioa_data = ioa_data;
kref_init(&dump->kref);
dump->ioa_cfg = ioa_cfg;
@ -3932,6 +3978,7 @@ static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg)
if (INACTIVE != ioa_cfg->sdt_state) {
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
vfree(dump->ioa_dump.ioa_data);
kfree(dump);
return 0;
}
@ -4953,9 +5000,35 @@ static int ipr_eh_abort(struct scsi_cmnd * scsi_cmd)
* IRQ_NONE / IRQ_HANDLED
**/
static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg,
volatile u32 int_reg)
u32 int_reg)
{
irqreturn_t rc = IRQ_HANDLED;
u32 int_mask_reg;
int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32);
int_reg &= ~int_mask_reg;
/* If an interrupt on the adapter did not occur, ignore it.
* Or in the case of SIS 64, check for a stage change interrupt.
*/
if ((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0) {
if (ioa_cfg->sis64) {
int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) {
/* clear stage change */
writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg);
int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
list_del(&ioa_cfg->reset_cmd->queue);
del_timer(&ioa_cfg->reset_cmd->timer);
ipr_reset_ioa_job(ioa_cfg->reset_cmd);
return IRQ_HANDLED;
}
}
return IRQ_NONE;
}
if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) {
/* Mask the interrupt */
@ -4968,6 +5041,13 @@ static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg,
list_del(&ioa_cfg->reset_cmd->queue);
del_timer(&ioa_cfg->reset_cmd->timer);
ipr_reset_ioa_job(ioa_cfg->reset_cmd);
} else if ((int_reg & IPR_PCII_HRRQ_UPDATED) == int_reg) {
if (ipr_debug && printk_ratelimit())
dev_err(&ioa_cfg->pdev->dev,
"Spurious interrupt detected. 0x%08X\n", int_reg);
writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32);
int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
return IRQ_NONE;
} else {
if (int_reg & IPR_PCII_IOA_UNIT_CHECKED)
ioa_cfg->ioa_unit_checked = 1;
@ -5016,10 +5096,11 @@ static irqreturn_t ipr_isr(int irq, void *devp)
{
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp;
unsigned long lock_flags = 0;
volatile u32 int_reg, int_mask_reg;
u32 int_reg = 0;
u32 ioasc;
u16 cmd_index;
int num_hrrq = 0;
int irq_none = 0;
struct ipr_cmnd *ipr_cmd;
irqreturn_t rc = IRQ_NONE;
@ -5031,33 +5112,6 @@ static irqreturn_t ipr_isr(int irq, void *devp)
return IRQ_NONE;
}
int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32);
int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg;
/* If an interrupt on the adapter did not occur, ignore it.
* Or in the case of SIS 64, check for a stage change interrupt.
*/
if (unlikely((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0)) {
if (ioa_cfg->sis64) {
int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) {
/* clear stage change */
writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg);
int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
list_del(&ioa_cfg->reset_cmd->queue);
del_timer(&ioa_cfg->reset_cmd->timer);
ipr_reset_ioa_job(ioa_cfg->reset_cmd);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
return IRQ_HANDLED;
}
}
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
return IRQ_NONE;
}
while (1) {
ipr_cmd = NULL;
@ -5097,7 +5151,7 @@ static irqreturn_t ipr_isr(int irq, void *devp)
/* Clear the PCI interrupt */
do {
writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32);
int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg;
int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
} while (int_reg & IPR_PCII_HRRQ_UPDATED &&
num_hrrq++ < IPR_MAX_HRRQ_RETRIES);
@ -5107,6 +5161,9 @@ static irqreturn_t ipr_isr(int irq, void *devp)
return IRQ_HANDLED;
}
} else if (rc == IRQ_NONE && irq_none == 0) {
int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
irq_none++;
} else
break;
}
@ -5143,7 +5200,8 @@ static int ipr_build_ioadl64(struct ipr_ioa_cfg *ioa_cfg,
nseg = scsi_dma_map(scsi_cmd);
if (nseg < 0) {
dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n");
if (printk_ratelimit())
dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n");
return -1;
}
@ -5773,7 +5831,8 @@ static int ipr_queuecommand_lck(struct scsi_cmnd *scsi_cmd,
}
ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_LINK_DESC;
ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_DELAY_AFTER_RST;
if (ipr_is_gscsi(res))
ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_DELAY_AFTER_RST;
ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_ALIGNED_BFR;
ioarcb->cmd_pkt.flags_lo |= ipr_get_task_attributes(scsi_cmd);
}
@ -7516,7 +7575,7 @@ static int ipr_reset_get_unit_check_job(struct ipr_cmnd *ipr_cmd)
static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
{
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
volatile u32 int_reg;
u32 int_reg;
ENTER;
ioa_cfg->pdev->state_saved = true;
@ -7555,7 +7614,10 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
ipr_cmd->job_step = ipr_reset_enable_ioa;
if (GET_DUMP == ioa_cfg->sdt_state) {
ipr_reset_start_timer(ipr_cmd, IPR_DUMP_TIMEOUT);
if (ioa_cfg->sis64)
ipr_reset_start_timer(ipr_cmd, IPR_SIS64_DUMP_TIMEOUT);
else
ipr_reset_start_timer(ipr_cmd, IPR_SIS32_DUMP_TIMEOUT);
ipr_cmd->job_step = ipr_reset_wait_for_dump;
schedule_work(&ioa_cfg->work_q);
return IPR_RC_JOB_RETURN;

View File

@ -38,8 +38,8 @@
/*
* Literals
*/
#define IPR_DRIVER_VERSION "2.5.1"
#define IPR_DRIVER_DATE "(August 10, 2010)"
#define IPR_DRIVER_VERSION "2.5.2"
#define IPR_DRIVER_DATE "(April 27, 2011)"
/*
* IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
@ -217,7 +217,8 @@
#define IPR_CHECK_FOR_RESET_TIMEOUT (HZ / 10)
#define IPR_WAIT_FOR_BIST_TIMEOUT (2 * HZ)
#define IPR_PCI_RESET_TIMEOUT (HZ / 2)
#define IPR_DUMP_TIMEOUT (15 * HZ)
#define IPR_SIS32_DUMP_TIMEOUT (15 * HZ)
#define IPR_SIS64_DUMP_TIMEOUT (40 * HZ)
#define IPR_DUMP_DELAY_SECONDS 4
#define IPR_DUMP_DELAY_TIMEOUT (IPR_DUMP_DELAY_SECONDS * HZ)
@ -285,9 +286,12 @@ IPR_PCII_NO_HOST_RRQ | IPR_PCII_IOARRIN_LOST | IPR_PCII_MMIO_ERROR)
/*
* Dump literals
*/
#define IPR_MAX_IOA_DUMP_SIZE (4 * 1024 * 1024)
#define IPR_NUM_SDT_ENTRIES 511
#define IPR_MAX_NUM_DUMP_PAGES ((IPR_MAX_IOA_DUMP_SIZE / PAGE_SIZE) + 1)
#define IPR_FMT2_MAX_IOA_DUMP_SIZE (4 * 1024 * 1024)
#define IPR_FMT3_MAX_IOA_DUMP_SIZE (32 * 1024 * 1024)
#define IPR_FMT2_NUM_SDT_ENTRIES 511
#define IPR_FMT3_NUM_SDT_ENTRIES 0xFFF
#define IPR_FMT2_MAX_NUM_DUMP_PAGES ((IPR_FMT2_MAX_IOA_DUMP_SIZE / PAGE_SIZE) + 1)
#define IPR_FMT3_MAX_NUM_DUMP_PAGES ((IPR_FMT3_MAX_IOA_DUMP_SIZE / PAGE_SIZE) + 1)
/*
* Misc literals
@ -474,7 +478,7 @@ struct ipr_cmd_pkt {
u8 flags_lo;
#define IPR_FLAGS_LO_ALIGNED_BFR 0x20
#define IPR_FLAGS_LO_DELAY_AFTER_RST 0x10
#define IPR_FLAGS_LO_DELAY_AFTER_RST 0x10
#define IPR_FLAGS_LO_UNTAGGED_TASK 0x00
#define IPR_FLAGS_LO_SIMPLE_TASK 0x02
#define IPR_FLAGS_LO_ORDERED_TASK 0x04
@ -1164,7 +1168,7 @@ struct ipr_sdt_header {
struct ipr_sdt {
struct ipr_sdt_header hdr;
struct ipr_sdt_entry entry[IPR_NUM_SDT_ENTRIES];
struct ipr_sdt_entry entry[IPR_FMT3_NUM_SDT_ENTRIES];
}__attribute__((packed, aligned (4)));
struct ipr_uc_sdt {
@ -1608,7 +1612,7 @@ struct ipr_driver_dump {
struct ipr_ioa_dump {
struct ipr_dump_entry_header hdr;
struct ipr_sdt sdt;
__be32 *ioa_data[IPR_MAX_NUM_DUMP_PAGES];
__be32 **ioa_data;
u32 reserved;
u32 next_page_index;
u32 page_offset;

View File

@ -57,9 +57,6 @@ static struct kmem_cache *scsi_pkt_cachep;
#define FC_SRB_READ (1 << 1)
#define FC_SRB_WRITE (1 << 0)
/* constant added to e_d_tov timeout to get rec_tov value */
#define REC_TOV_CONST 1
/*
* The SCp.ptr should be tested and set under the scsi_pkt_queue lock
*/
@ -248,7 +245,7 @@ static inline void fc_fcp_unlock_pkt(struct fc_fcp_pkt *fsp)
/**
* fc_fcp_timer_set() - Start a timer for a fcp_pkt
* @fsp: The FCP packet to start a timer for
* @delay: The timeout period for the timer
* @delay: The timeout period in jiffies
*/
static void fc_fcp_timer_set(struct fc_fcp_pkt *fsp, unsigned long delay)
{
@ -335,22 +332,23 @@ static void fc_fcp_ddp_done(struct fc_fcp_pkt *fsp)
/**
* fc_fcp_can_queue_ramp_up() - increases can_queue
* @lport: lport to ramp up can_queue
*
* Locking notes: Called with Scsi_Host lock held
*/
static void fc_fcp_can_queue_ramp_up(struct fc_lport *lport)
{
struct fc_fcp_internal *si = fc_get_scsi_internal(lport);
unsigned long flags;
int can_queue;
spin_lock_irqsave(lport->host->host_lock, flags);
if (si->last_can_queue_ramp_up_time &&
(time_before(jiffies, si->last_can_queue_ramp_up_time +
FC_CAN_QUEUE_PERIOD)))
return;
goto unlock;
if (time_before(jiffies, si->last_can_queue_ramp_down_time +
FC_CAN_QUEUE_PERIOD))
return;
goto unlock;
si->last_can_queue_ramp_up_time = jiffies;
@ -362,6 +360,9 @@ static void fc_fcp_can_queue_ramp_up(struct fc_lport *lport)
lport->host->can_queue = can_queue;
shost_printk(KERN_ERR, lport->host, "libfc: increased "
"can_queue to %d.\n", can_queue);
unlock:
spin_unlock_irqrestore(lport->host->host_lock, flags);
}
/**
@ -373,18 +374,19 @@ static void fc_fcp_can_queue_ramp_up(struct fc_lport *lport)
* commands complete or timeout, then try again with a reduced
* can_queue. Eventually we will hit the point where we run
* on all reserved structs.
*
* Locking notes: Called with Scsi_Host lock held
*/
static void fc_fcp_can_queue_ramp_down(struct fc_lport *lport)
{
struct fc_fcp_internal *si = fc_get_scsi_internal(lport);
unsigned long flags;
int can_queue;
spin_lock_irqsave(lport->host->host_lock, flags);
if (si->last_can_queue_ramp_down_time &&
(time_before(jiffies, si->last_can_queue_ramp_down_time +
FC_CAN_QUEUE_PERIOD)))
return;
goto unlock;
si->last_can_queue_ramp_down_time = jiffies;
@ -395,6 +397,9 @@ static void fc_fcp_can_queue_ramp_down(struct fc_lport *lport)
lport->host->can_queue = can_queue;
shost_printk(KERN_ERR, lport->host, "libfc: Could not allocate frame.\n"
"Reducing can_queue to %d.\n", can_queue);
unlock:
spin_unlock_irqrestore(lport->host->host_lock, flags);
}
/*
@ -409,16 +414,13 @@ static inline struct fc_frame *fc_fcp_frame_alloc(struct fc_lport *lport,
size_t len)
{
struct fc_frame *fp;
unsigned long flags;
fp = fc_frame_alloc(lport, len);
if (likely(fp))
return fp;
/* error case */
spin_lock_irqsave(lport->host->host_lock, flags);
fc_fcp_can_queue_ramp_down(lport);
spin_unlock_irqrestore(lport->host->host_lock, flags);
return NULL;
}
@ -1093,16 +1095,14 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp)
/**
* get_fsp_rec_tov() - Helper function to get REC_TOV
* @fsp: the FCP packet
*
* Returns rec tov in jiffies as rpriv->e_d_tov + 1 second
*/
static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp)
{
struct fc_rport *rport;
struct fc_rport_libfc_priv *rpriv;
struct fc_rport_libfc_priv *rpriv = fsp->rport->dd_data;
rport = fsp->rport;
rpriv = rport->dd_data;
return rpriv->e_d_tov + REC_TOV_CONST;
return msecs_to_jiffies(rpriv->e_d_tov) + HZ;
}
/**
@ -1122,7 +1122,6 @@ static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp,
struct fc_rport_libfc_priv *rpriv;
const size_t len = sizeof(fsp->cdb_cmd);
int rc = 0;
unsigned int rec_tov;
if (fc_fcp_lock_pkt(fsp))
return 0;
@ -1153,12 +1152,9 @@ static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp,
fsp->seq_ptr = seq;
fc_fcp_pkt_hold(fsp); /* hold for fc_fcp_pkt_destroy */
rec_tov = get_fsp_rec_tov(fsp);
setup_timer(&fsp->timer, fc_fcp_timeout, (unsigned long)fsp);
if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED)
fc_fcp_timer_set(fsp, rec_tov);
fc_fcp_timer_set(fsp, get_fsp_rec_tov(fsp));
unlock:
fc_fcp_unlock_pkt(fsp);
@ -1235,16 +1231,14 @@ static void fc_lun_reset_send(unsigned long data)
{
struct fc_fcp_pkt *fsp = (struct fc_fcp_pkt *)data;
struct fc_lport *lport = fsp->lp;
unsigned int rec_tov;
if (lport->tt.fcp_cmd_send(lport, fsp, fc_tm_done)) {
if (fsp->recov_retry++ >= FC_MAX_RECOV_RETRY)
return;
if (fc_fcp_lock_pkt(fsp))
return;
rec_tov = get_fsp_rec_tov(fsp);
setup_timer(&fsp->timer, fc_lun_reset_send, (unsigned long)fsp);
fc_fcp_timer_set(fsp, rec_tov);
fc_fcp_timer_set(fsp, get_fsp_rec_tov(fsp));
fc_fcp_unlock_pkt(fsp);
}
}
@ -1536,12 +1530,11 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
}
fc_fcp_srr(fsp, r_ctl, offset);
} else if (e_stat & ESB_ST_SEQ_INIT) {
unsigned int rec_tov = get_fsp_rec_tov(fsp);
/*
* The remote port has the initiative, so just
* keep waiting for it to complete.
*/
fc_fcp_timer_set(fsp, rec_tov);
fc_fcp_timer_set(fsp, get_fsp_rec_tov(fsp));
} else {
/*
@ -1705,7 +1698,6 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
{
struct fc_fcp_pkt *fsp = arg;
struct fc_frame_header *fh;
unsigned int rec_tov;
if (IS_ERR(fp)) {
fc_fcp_srr_error(fsp, fp);
@ -1732,8 +1724,7 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
switch (fc_frame_payload_op(fp)) {
case ELS_LS_ACC:
fsp->recov_retry = 0;
rec_tov = get_fsp_rec_tov(fsp);
fc_fcp_timer_set(fsp, rec_tov);
fc_fcp_timer_set(fsp, get_fsp_rec_tov(fsp));
break;
case ELS_LS_RJT:
default:

View File

@ -1590,7 +1590,6 @@ void fc_lport_enter_flogi(struct fc_lport *lport)
*/
int fc_lport_config(struct fc_lport *lport)
{
INIT_LIST_HEAD(&lport->ema_list);
INIT_DELAYED_WORK(&lport->retry_work, fc_lport_timeout);
mutex_init(&lport->lp_mutex);

View File

@ -805,6 +805,8 @@ struct lpfc_hba {
struct dentry *idiag_root;
struct dentry *idiag_pci_cfg;
struct dentry *idiag_que_info;
struct dentry *idiag_que_acc;
struct dentry *idiag_drb_acc;
#endif
/* Used for deferred freeing of ELS data buffers */

View File

@ -2426,6 +2426,7 @@ lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
{
struct bsg_job_data *dd_data;
struct fc_bsg_job *job;
struct lpfc_mbx_nembed_cmd *nembed_sge;
uint32_t size;
unsigned long flags;
uint8_t *to;
@ -2469,9 +2470,8 @@ lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
memcpy(to, from, size);
} else if ((phba->sli_rev == LPFC_SLI_REV4) &&
(pmboxq->u.mb.mbxCommand == MBX_SLI4_CONFIG)) {
struct lpfc_mbx_nembed_cmd *nembed_sge =
(struct lpfc_mbx_nembed_cmd *)
&pmboxq->u.mb.un.varWords[0];
nembed_sge = (struct lpfc_mbx_nembed_cmd *)
&pmboxq->u.mb.un.varWords[0];
from = (uint8_t *)dd_data->context_un.mbox.dmp->dma.
virt;
@ -2496,16 +2496,18 @@ lpfc_bsg_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
job->reply_payload.sg_cnt,
from, size);
job->reply->result = 0;
/* need to hold the lock until we set job->dd_data to NULL
* to hold off the timeout handler returning to the mid-layer
* while we are still processing the job.
*/
job->dd_data = NULL;
dd_data->context_un.mbox.set_job = NULL;
spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
job->job_done(job);
} else {
dd_data->context_un.mbox.set_job = NULL;
spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
}
dd_data->context_un.mbox.set_job = NULL;
/* need to hold the lock until we call job done to hold off
* the timeout handler returning to the midlayer while
* we are stillprocessing the job
*/
spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
kfree(dd_data->context_un.mbox.mb);
mempool_free(dd_data->context_un.mbox.pmboxq, phba->mbox_mem_pool);
@ -2644,6 +2646,11 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
struct ulp_bde64 *rxbpl = NULL;
struct dfc_mbox_req *mbox_req = (struct dfc_mbox_req *)
job->request->rqst_data.h_vendor.vendor_cmd;
struct READ_EVENT_LOG_VAR *rdEventLog;
uint32_t transmit_length, receive_length, mode;
struct lpfc_mbx_nembed_cmd *nembed_sge;
struct mbox_header *header;
struct ulp_bde64 *bde;
uint8_t *ext = NULL;
int rc = 0;
uint8_t *from;
@ -2651,9 +2658,16 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
/* in case no data is transferred */
job->reply->reply_payload_rcv_len = 0;
/* sanity check to protect driver */
if (job->reply_payload.payload_len > BSG_MBOX_SIZE ||
job->request_payload.payload_len > BSG_MBOX_SIZE) {
rc = -ERANGE;
goto job_done;
}
/* check if requested extended data lengths are valid */
if ((mbox_req->inExtWLen > MAILBOX_EXT_SIZE) ||
(mbox_req->outExtWLen > MAILBOX_EXT_SIZE)) {
if ((mbox_req->inExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t)) ||
(mbox_req->outExtWLen > BSG_MBOX_SIZE/sizeof(uint32_t))) {
rc = -ERANGE;
goto job_done;
}
@ -2744,8 +2758,8 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
* use ours
*/
if (pmb->mbxCommand == MBX_RUN_BIU_DIAG64) {
uint32_t transmit_length = pmb->un.varWords[1];
uint32_t receive_length = pmb->un.varWords[4];
transmit_length = pmb->un.varWords[1];
receive_length = pmb->un.varWords[4];
/* transmit length cannot be greater than receive length or
* mailbox extension size
*/
@ -2795,10 +2809,9 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
from += sizeof(MAILBOX_t);
memcpy((uint8_t *)dmp->dma.virt, from, transmit_length);
} else if (pmb->mbxCommand == MBX_READ_EVENT_LOG) {
struct READ_EVENT_LOG_VAR *rdEventLog =
&pmb->un.varRdEventLog ;
uint32_t receive_length = rdEventLog->rcv_bde64.tus.f.bdeSize;
uint32_t mode = bf_get(lpfc_event_log, rdEventLog);
rdEventLog = &pmb->un.varRdEventLog;
receive_length = rdEventLog->rcv_bde64.tus.f.bdeSize;
mode = bf_get(lpfc_event_log, rdEventLog);
/* receive length cannot be greater than mailbox
* extension size
@ -2843,7 +2856,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
/* rebuild the command for sli4 using our own buffers
* like we do for biu diags
*/
uint32_t receive_length = pmb->un.varWords[2];
receive_length = pmb->un.varWords[2];
/* receive length cannot be greater than mailbox
* extension size
*/
@ -2879,8 +2892,7 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
pmb->un.varWords[4] = putPaddrHigh(dmp->dma.phys);
} else if ((pmb->mbxCommand == MBX_UPDATE_CFG) &&
pmb->un.varUpdateCfg.co) {
struct ulp_bde64 *bde =
(struct ulp_bde64 *)&pmb->un.varWords[4];
bde = (struct ulp_bde64 *)&pmb->un.varWords[4];
/* bde size cannot be greater than mailbox ext size */
if (bde->tus.f.bdeSize > MAILBOX_EXT_SIZE) {
@ -2921,10 +2933,6 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job,
memcpy((uint8_t *)dmp->dma.virt, from,
bde->tus.f.bdeSize);
} else if (pmb->mbxCommand == MBX_SLI4_CONFIG) {
struct lpfc_mbx_nembed_cmd *nembed_sge;
struct mbox_header *header;
uint32_t receive_length;
/* rebuild the command for sli4 using our own buffers
* like we do for biu diags
*/
@ -3386,6 +3394,7 @@ no_dd_data:
job->dd_data = NULL;
return rc;
}
/**
* lpfc_bsg_hst_vendor - process a vendor-specific fc_bsg_job
* @job: fc_bsg_job to handle

View File

@ -109,3 +109,133 @@ struct menlo_response {
uint32_t xri; /* return the xri of the iocb exchange */
};
/*
* macros and data structures for handling sli-config mailbox command
* pass-through support, this header file is shared between user and
* kernel spaces, note the set of macros are duplicates from lpfc_hw4.h,
* with macro names prefixed with bsg_, as the macros defined in
* lpfc_hw4.h are not accessible from user space.
*/
/* Macros to deal with bit fields. Each bit field must have 3 #defines
* associated with it (_SHIFT, _MASK, and _WORD).
* EG. For a bit field that is in the 7th bit of the "field4" field of a
* structure and is 2 bits in size the following #defines must exist:
* struct temp {
* uint32_t field1;
* uint32_t field2;
* uint32_t field3;
* uint32_t field4;
* #define example_bit_field_SHIFT 7
* #define example_bit_field_MASK 0x03
* #define example_bit_field_WORD field4
* uint32_t field5;
* };
* Then the macros below may be used to get or set the value of that field.
* EG. To get the value of the bit field from the above example:
* struct temp t1;
* value = bsg_bf_get(example_bit_field, &t1);
* And then to set that bit field:
* bsg_bf_set(example_bit_field, &t1, 2);
* Or clear that bit field:
* bsg_bf_set(example_bit_field, &t1, 0);
*/
#define bsg_bf_get_le32(name, ptr) \
((le32_to_cpu((ptr)->name##_WORD) >> name##_SHIFT) & name##_MASK)
#define bsg_bf_get(name, ptr) \
(((ptr)->name##_WORD >> name##_SHIFT) & name##_MASK)
#define bsg_bf_set_le32(name, ptr, value) \
((ptr)->name##_WORD = cpu_to_le32(((((value) & \
name##_MASK) << name##_SHIFT) | (le32_to_cpu((ptr)->name##_WORD) & \
~(name##_MASK << name##_SHIFT)))))
#define bsg_bf_set(name, ptr, value) \
((ptr)->name##_WORD = ((((value) & name##_MASK) << name##_SHIFT) | \
((ptr)->name##_WORD & ~(name##_MASK << name##_SHIFT))))
/*
* The sli_config structure specified here is based on the following
* restriction:
*
* -- SLI_CONFIG EMB=0, carrying MSEs, will carry subcommands without
* carrying HBD.
* -- SLI_CONFIG EMB=1, not carrying MSE, will carry subcommands with or
* without carrying HBDs.
*/
struct lpfc_sli_config_mse {
uint32_t pa_lo;
uint32_t pa_hi;
uint32_t buf_len;
#define lpfc_mbox_sli_config_mse_len_SHIFT 0
#define lpfc_mbox_sli_config_mse_len_MASK 0xffffff
#define lpfc_mbox_sli_config_mse_len_WORD buf_len
};
struct lpfc_sli_config_subcmd_hbd {
uint32_t buf_len;
#define lpfc_mbox_sli_config_ecmn_hbd_len_SHIFT 0
#define lpfc_mbox_sli_config_ecmn_hbd_len_MASK 0xffffff
#define lpfc_mbox_sli_config_ecmn_hbd_len_WORD buf_len
uint32_t pa_lo;
uint32_t pa_hi;
};
struct lpfc_sli_config_hdr {
uint32_t word1;
#define lpfc_mbox_hdr_emb_SHIFT 0
#define lpfc_mbox_hdr_emb_MASK 0x00000001
#define lpfc_mbox_hdr_emb_WORD word1
#define lpfc_mbox_hdr_mse_cnt_SHIFT 3
#define lpfc_mbox_hdr_mse_cnt_MASK 0x0000001f
#define lpfc_mbox_hdr_mse_cnt_WORD word1
uint32_t payload_length;
uint32_t tag_lo;
uint32_t tag_hi;
uint32_t reserved5;
};
struct lpfc_sli_config_generic {
struct lpfc_sli_config_hdr sli_config_hdr;
#define LPFC_MBX_SLI_CONFIG_MAX_MSE 19
struct lpfc_sli_config_mse mse[LPFC_MBX_SLI_CONFIG_MAX_MSE];
};
struct lpfc_sli_config_subcmnd {
struct lpfc_sli_config_hdr sli_config_hdr;
uint32_t word6;
#define lpfc_subcmnd_opcode_SHIFT 0
#define lpfc_subcmnd_opcode_MASK 0xff
#define lpfc_subcmnd_opcode_WORD word6
#define lpfc_subcmnd_subsys_SHIFT 8
#define lpfc_subcmnd_subsys_MASK 0xff
#define lpfc_subcmnd_subsys_WORD word6
uint32_t timeout;
uint32_t request_length;
uint32_t word9;
#define lpfc_subcmnd_version_SHIFT 0
#define lpfc_subcmnd_version_MASK 0xff
#define lpfc_subcmnd_version_WORD word9
uint32_t word10;
#define lpfc_subcmnd_ask_rd_len_SHIFT 0
#define lpfc_subcmnd_ask_rd_len_MASK 0xffffff
#define lpfc_subcmnd_ask_rd_len_WORD word10
uint32_t rd_offset;
uint32_t obj_name[26];
uint32_t hbd_count;
#define LPFC_MBX_SLI_CONFIG_MAX_HBD 10
struct lpfc_sli_config_subcmd_hbd hbd[LPFC_MBX_SLI_CONFIG_MAX_HBD];
};
struct lpfc_sli_config_mbox {
uint32_t word0;
#define lpfc_mqe_status_SHIFT 16
#define lpfc_mqe_status_MASK 0x0000FFFF
#define lpfc_mqe_status_WORD word0
#define lpfc_mqe_command_SHIFT 8
#define lpfc_mqe_command_MASK 0x000000FF
#define lpfc_mqe_command_WORD word0
union {
struct lpfc_sli_config_generic sli_config_generic;
struct lpfc_sli_config_subcmnd sli_config_subcmnd;
} un;
};

File diff suppressed because it is too large Load Diff

View File

@ -39,13 +39,42 @@
/* hbqinfo output buffer size */
#define LPFC_HBQINFO_SIZE 8192
/* rdPciConf output buffer size */
/* pciConf */
#define LPFC_PCI_CFG_BROWSE 0xffff
#define LPFC_PCI_CFG_RD_CMD_ARG 2
#define LPFC_PCI_CFG_WR_CMD_ARG 3
#define LPFC_PCI_CFG_SIZE 4096
#define LPFC_PCI_CFG_RD_BUF_SIZE (LPFC_PCI_CFG_SIZE/2)
#define LPFC_PCI_CFG_RD_SIZE (LPFC_PCI_CFG_SIZE/4)
/* queue info output buffer size */
#define LPFC_QUE_INFO_GET_BUF_SIZE 2048
/* queue info */
#define LPFC_QUE_INFO_GET_BUF_SIZE 4096
/* queue acc */
#define LPFC_QUE_ACC_BROWSE 0xffff
#define LPFC_QUE_ACC_RD_CMD_ARG 4
#define LPFC_QUE_ACC_WR_CMD_ARG 6
#define LPFC_QUE_ACC_BUF_SIZE 4096
#define LPFC_QUE_ACC_SIZE (LPFC_QUE_ACC_BUF_SIZE/2)
#define LPFC_IDIAG_EQ 1
#define LPFC_IDIAG_CQ 2
#define LPFC_IDIAG_MQ 3
#define LPFC_IDIAG_WQ 4
#define LPFC_IDIAG_RQ 5
/* doorbell acc */
#define LPFC_DRB_ACC_ALL 0xffff
#define LPFC_DRB_ACC_RD_CMD_ARG 1
#define LPFC_DRB_ACC_WR_CMD_ARG 2
#define LPFC_DRB_ACC_BUF_SIZE 256
#define LPFC_DRB_EQCQ 1
#define LPFC_DRB_MQ 2
#define LPFC_DRB_WQ 3
#define LPFC_DRB_RQ 4
#define LPFC_DRB_MAX 4
#define SIZE_U8 sizeof(uint8_t)
#define SIZE_U16 sizeof(uint16_t)
@ -73,13 +102,23 @@ struct lpfc_idiag_offset {
uint32_t last_rd;
};
#define LPFC_IDIAG_CMD_DATA_SIZE 4
#define LPFC_IDIAG_CMD_DATA_SIZE 8
struct lpfc_idiag_cmd {
uint32_t opcode;
#define LPFC_IDIAG_CMD_PCICFG_RD 0x00000001
#define LPFC_IDIAG_CMD_PCICFG_WR 0x00000002
#define LPFC_IDIAG_CMD_PCICFG_ST 0x00000003
#define LPFC_IDIAG_CMD_PCICFG_CL 0x00000004
#define LPFC_IDIAG_CMD_QUEACC_RD 0x00000011
#define LPFC_IDIAG_CMD_QUEACC_WR 0x00000012
#define LPFC_IDIAG_CMD_QUEACC_ST 0x00000013
#define LPFC_IDIAG_CMD_QUEACC_CL 0x00000014
#define LPFC_IDIAG_CMD_DRBACC_RD 0x00000021
#define LPFC_IDIAG_CMD_DRBACC_WR 0x00000022
#define LPFC_IDIAG_CMD_DRBACC_ST 0x00000023
#define LPFC_IDIAG_CMD_DRBACC_CL 0x00000024
uint32_t data[LPFC_IDIAG_CMD_DATA_SIZE];
};
@ -87,6 +126,7 @@ struct lpfc_idiag {
uint32_t active;
struct lpfc_idiag_cmd cmd;
struct lpfc_idiag_offset offset;
void *ptr_private;
};
#endif

View File

@ -670,6 +670,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
* Driver needs to re-reg VPI in order for f/w
* to update the MAC address.
*/
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
lpfc_register_new_vport(phba, vport, ndlp);
return 0;
}
@ -869,8 +870,8 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
*/
if ((phba->hba_flag & HBA_FIP_SUPPORT) &&
(phba->fcf.fcf_flag & FCF_DISCOVERY) &&
(irsp->ulpStatus != IOSTAT_LOCAL_REJECT) &&
(irsp->un.ulpWord[4] != IOERR_SLI_ABORTED)) {
!((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
(irsp->un.ulpWord[4] == IOERR_SLI_ABORTED))) {
lpfc_printf_log(phba, KERN_WARNING, LOG_FIP | LOG_ELS,
"2611 FLOGI failed on FCF (x%x), "
"status:x%x/x%x, tmo:x%x, perform "
@ -1085,14 +1086,15 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
if (sp->cmn.fcphHigh < FC_PH3)
sp->cmn.fcphHigh = FC_PH3;
if ((phba->sli_rev == LPFC_SLI_REV4) &&
(bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
LPFC_SLI_INTF_IF_TYPE_0)) {
elsiocb->iocb.ulpCt_h = ((SLI4_CT_FCFI >> 1) & 1);
elsiocb->iocb.ulpCt_l = (SLI4_CT_FCFI & 1);
/* FLOGI needs to be 3 for WQE FCFI */
/* Set the fcfi to the fcfi we registered with */
elsiocb->iocb.ulpContext = phba->fcf.fcfi;
if (phba->sli_rev == LPFC_SLI_REV4) {
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
LPFC_SLI_INTF_IF_TYPE_0) {
elsiocb->iocb.ulpCt_h = ((SLI4_CT_FCFI >> 1) & 1);
elsiocb->iocb.ulpCt_l = (SLI4_CT_FCFI & 1);
/* FLOGI needs to be 3 for WQE FCFI */
/* Set the fcfi to the fcfi we registered with */
elsiocb->iocb.ulpContext = phba->fcf.fcfi;
}
} else if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
sp->cmn.request_multiple_Nport = 1;
/* For FLOGI, Let FLOGI rsp set the NPortID for VPI 0 */
@ -4107,13 +4109,13 @@ lpfc_els_clear_rrq(struct lpfc_vport *vport,
pcmd += sizeof(uint32_t);
rrq = (struct RRQ *)pcmd;
rrq->rrq_exchg = be32_to_cpu(rrq->rrq_exchg);
rxid = be16_to_cpu(bf_get(rrq_rxid, rrq));
rxid = bf_get(rrq_rxid, rrq);
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"2883 Clear RRQ for SID:x%x OXID:x%x RXID:x%x"
" x%x x%x\n",
be32_to_cpu(bf_get(rrq_did, rrq)),
be16_to_cpu(bf_get(rrq_oxid, rrq)),
bf_get(rrq_oxid, rrq),
rxid,
iocb->iotag, iocb->iocb.ulpContext);
@ -4121,7 +4123,7 @@ lpfc_els_clear_rrq(struct lpfc_vport *vport,
"Clear RRQ: did:x%x flg:x%x exchg:x%.08x",
ndlp->nlp_DID, ndlp->nlp_flag, rrq->rrq_exchg);
if (vport->fc_myDID == be32_to_cpu(bf_get(rrq_did, rrq)))
xri = be16_to_cpu(bf_get(rrq_oxid, rrq));
xri = bf_get(rrq_oxid, rrq);
else
xri = rxid;
prrq = lpfc_get_active_rrq(vport, xri, ndlp->nlp_DID);
@ -7290,8 +7292,9 @@ lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_vport *vport = cmdiocb->vport;
IOCB_t *irsp;
struct lpfc_nodelist *ndlp;
ndlp = (struct lpfc_nodelist *)cmdiocb->context1;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
ndlp = (struct lpfc_nodelist *)cmdiocb->context1;
irsp = &rspiocb->iocb;
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
"LOGO npiv cmpl: status:x%x/x%x did:x%x",
@ -7302,6 +7305,19 @@ lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
/* Trigger the release of the ndlp after logo */
lpfc_nlp_put(ndlp);
/* NPIV LOGO completes to NPort <nlp_DID> */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"2928 NPIV LOGO completes to NPort x%x "
"Data: x%x x%x x%x x%x\n",
ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4],
irsp->ulpTimeout, vport->num_disc_nodes);
if (irsp->ulpStatus == IOSTAT_SUCCESS) {
spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~FC_FABRIC;
spin_unlock_irq(shost->host_lock);
}
}
/**

View File

@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2009 Emulex. All rights reserved. *
* Copyright (C) 2004-2011 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
@ -3569,6 +3569,10 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
"rport add: did:x%x flg:x%x type x%x",
ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type);
/* Don't add the remote port if unloading. */
if (vport->load_flag & FC_UNLOADING)
return;
ndlp->rport = rport = fc_remote_port_add(shost, 0, &rport_ids);
if (!rport || !get_device(&rport->dev)) {
dev_printk(KERN_WARNING, &phba->pcidev->dev,

View File

@ -1059,6 +1059,11 @@ struct rq_context {
#define lpfc_rq_context_rqe_size_SHIFT 8 /* Version 1 Only */
#define lpfc_rq_context_rqe_size_MASK 0x0000000F
#define lpfc_rq_context_rqe_size_WORD word0
#define LPFC_RQE_SIZE_8 2
#define LPFC_RQE_SIZE_16 3
#define LPFC_RQE_SIZE_32 4
#define LPFC_RQE_SIZE_64 5
#define LPFC_RQE_SIZE_128 6
#define lpfc_rq_context_page_size_SHIFT 0 /* Version 1 Only */
#define lpfc_rq_context_page_size_MASK 0x000000FF
#define lpfc_rq_context_page_size_WORD word0
@ -2108,6 +2113,8 @@ struct lpfc_mbx_pc_sli4_params {
#define sgl_pp_align_WORD word12
uint32_t rsvd_13_63[51];
};
#define SLI4_PAGE_ALIGN(addr) (((addr)+((SLI4_PAGE_SIZE)-1)) \
&(~((SLI4_PAGE_SIZE)-1)))
struct lpfc_sli4_parameters {
uint32_t word0;
@ -2491,6 +2498,9 @@ struct wqe_common {
#define wqe_reqtag_SHIFT 0
#define wqe_reqtag_MASK 0x0000FFFF
#define wqe_reqtag_WORD word9
#define wqe_temp_rpi_SHIFT 16
#define wqe_temp_rpi_MASK 0x0000FFFF
#define wqe_temp_rpi_WORD word9
#define wqe_rcvoxid_SHIFT 16
#define wqe_rcvoxid_MASK 0x0000FFFF
#define wqe_rcvoxid_WORD word9
@ -2524,7 +2534,7 @@ struct wqe_common {
#define wqe_wqes_WORD word10
/* Note that this field overlaps above fields */
#define wqe_wqid_SHIFT 1
#define wqe_wqid_MASK 0x0000007f
#define wqe_wqid_MASK 0x00007fff
#define wqe_wqid_WORD word10
#define wqe_pri_SHIFT 16
#define wqe_pri_MASK 0x00000007
@ -2621,7 +2631,11 @@ struct xmit_els_rsp64_wqe {
uint32_t rsvd4;
struct wqe_did wqe_dest;
struct wqe_common wqe_com; /* words 6-11 */
uint32_t rsvd_12_15[4];
uint32_t word12;
#define wqe_rsp_temp_rpi_SHIFT 0
#define wqe_rsp_temp_rpi_MASK 0x0000FFFF
#define wqe_rsp_temp_rpi_WORD word12
uint32_t rsvd_13_15[3];
};
struct xmit_bls_rsp64_wqe {

View File

@ -3209,9 +3209,9 @@ lpfc_sli4_async_link_evt(struct lpfc_hba *phba,
phba->sli4_hba.link_state.logical_speed =
bf_get(lpfc_acqe_logical_link_speed, acqe_link);
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
"2900 Async FCoE Link event - Speed:%dGBit duplex:x%x "
"LA Type:x%x Port Type:%d Port Number:%d Logical "
"speed:%dMbps Fault:%d\n",
"2900 Async FC/FCoE Link event - Speed:%dGBit "
"duplex:x%x LA Type:x%x Port Type:%d Port Number:%d "
"Logical speed:%dMbps Fault:%d\n",
phba->sli4_hba.link_state.speed,
phba->sli4_hba.link_state.topology,
phba->sli4_hba.link_state.status,
@ -4906,6 +4906,7 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba)
uint16_t rpi_limit, curr_rpi_range;
struct lpfc_dmabuf *dmabuf;
struct lpfc_rpi_hdr *rpi_hdr;
uint32_t rpi_count;
rpi_limit = phba->sli4_hba.max_cfg_param.rpi_base +
phba->sli4_hba.max_cfg_param.max_rpi - 1;
@ -4920,7 +4921,9 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba)
* and to allow the full max_rpi range per port.
*/
if ((curr_rpi_range + (LPFC_RPI_HDR_COUNT - 1)) > rpi_limit)
return NULL;
rpi_count = rpi_limit - curr_rpi_range;
else
rpi_count = LPFC_RPI_HDR_COUNT;
/*
* First allocate the protocol header region for the port. The
@ -4961,7 +4964,7 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba)
* The next_rpi stores the next module-64 rpi value to post
* in any subsequent rpi memory region postings.
*/
phba->sli4_hba.next_rpi += LPFC_RPI_HDR_COUNT;
phba->sli4_hba.next_rpi += rpi_count;
spin_unlock_irq(&phba->hbalock);
return rpi_hdr;
@ -7004,7 +7007,8 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
lpfc_sli4_bar0_register_memmap(phba, if_type);
}
if (pci_resource_start(pdev, 2)) {
if ((if_type == LPFC_SLI_INTF_IF_TYPE_0) &&
(pci_resource_start(pdev, 2))) {
/*
* Map SLI4 if type 0 HBA Control Register base to a kernel
* virtual address and setup the registers.
@ -7021,7 +7025,8 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
lpfc_sli4_bar1_register_memmap(phba);
}
if (pci_resource_start(pdev, 4)) {
if ((if_type == LPFC_SLI_INTF_IF_TYPE_0) &&
(pci_resource_start(pdev, 4))) {
/*
* Map SLI4 if type 0 HBA Doorbell Register base to a kernel
* virtual address and setup the registers.

View File

@ -1736,7 +1736,7 @@ lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox,
}
/* Setup for the none-embedded mbox command */
pcount = (PAGE_ALIGN(length))/SLI4_PAGE_SIZE;
pcount = (SLI4_PAGE_ALIGN(length))/SLI4_PAGE_SIZE;
pcount = (pcount > LPFC_SLI4_MBX_SGE_MAX_PAGES) ?
LPFC_SLI4_MBX_SGE_MAX_PAGES : pcount;
/* Allocate record for keeping SGE virtual addresses */

View File

@ -3238,9 +3238,8 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
if (!lpfc_cmd) {
lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
"2873 SCSI Layer I/O Abort Request IO CMPL Status "
"x%x ID %d "
"LUN %d snum %#lx\n", ret, cmnd->device->id,
cmnd->device->lun, cmnd->serial_number);
"x%x ID %d LUN %d\n",
ret, cmnd->device->id, cmnd->device->lun);
return SUCCESS;
}
@ -3318,16 +3317,15 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
"0748 abort handler timed out waiting "
"for abort to complete: ret %#x, ID %d, "
"LUN %d, snum %#lx\n",
ret, cmnd->device->id, cmnd->device->lun,
cmnd->serial_number);
"LUN %d\n",
ret, cmnd->device->id, cmnd->device->lun);
}
out:
lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
"0749 SCSI Layer I/O Abort Request Status x%x ID %d "
"LUN %d snum %#lx\n", ret, cmnd->device->id,
cmnd->device->lun, cmnd->serial_number);
"LUN %d\n", ret, cmnd->device->id,
cmnd->device->lun);
return ret;
}

View File

@ -4769,8 +4769,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
else
phba->hba_flag &= ~HBA_FIP_SUPPORT;
if (phba->sli_rev != LPFC_SLI_REV4 ||
!(phba->hba_flag & HBA_FCOE_MODE)) {
if (phba->sli_rev != LPFC_SLI_REV4) {
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
"0376 READ_REV Error. SLI Level %d "
"FCoE enabled %d\n",
@ -5018,10 +5017,11 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
lpfc_reg_fcfi(phba, mboxq);
mboxq->vport = phba->pport;
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
if (rc == MBX_SUCCESS)
rc = 0;
else
if (rc != MBX_SUCCESS)
goto out_unset_queue;
rc = 0;
phba->fcf.fcfi = bf_get(lpfc_reg_fcfi_fcfi,
&mboxq->u.mqe.un.reg_fcfi);
}
/*
* The port is ready, set the host's link state to LINK_DOWN
@ -6402,6 +6402,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
uint32_t els_id = LPFC_ELS_ID_DEFAULT;
int numBdes, i;
struct ulp_bde64 bde;
struct lpfc_nodelist *ndlp;
fip = phba->hba_flag & HBA_FIP_SUPPORT;
/* The fcp commands will set command type */
@ -6447,6 +6448,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
switch (iocbq->iocb.ulpCommand) {
case CMD_ELS_REQUEST64_CR:
ndlp = (struct lpfc_nodelist *)iocbq->context1;
if (!iocbq->iocb.ulpLe) {
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"2007 Only Limited Edition cmd Format"
@ -6472,6 +6474,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
els_id = ((iocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK)
>> LPFC_FIP_ELS_ID_SHIFT);
}
bf_set(wqe_temp_rpi, &wqe->els_req.wqe_com, ndlp->nlp_rpi);
bf_set(wqe_els_id, &wqe->els_req.wqe_com, els_id);
bf_set(wqe_dbde, &wqe->els_req.wqe_com, 1);
bf_set(wqe_iod, &wqe->els_req.wqe_com, LPFC_WQE_IOD_READ);
@ -6604,6 +6607,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
command_type = OTHER_COMMAND;
break;
case CMD_XMIT_ELS_RSP64_CX:
ndlp = (struct lpfc_nodelist *)iocbq->context1;
/* words0-2 BDE memcpy */
/* word3 iocb=iotag32 wqe=response_payload_len */
wqe->xmit_els_rsp.response_payload_len = xmit_len;
@ -6626,6 +6630,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
bf_set(wqe_lenloc, &wqe->xmit_els_rsp.wqe_com,
LPFC_WQE_LENLOC_WORD3);
bf_set(wqe_ebde_cnt, &wqe->xmit_els_rsp.wqe_com, 0);
bf_set(wqe_rsp_temp_rpi, &wqe->xmit_els_rsp, ndlp->nlp_rpi);
command_type = OTHER_COMMAND;
break;
case CMD_CLOSE_XRI_CN:
@ -10522,8 +10527,8 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
bf_set(lpfc_mbox_hdr_version, &shdr->request,
phba->sli4_hba.pc_sli4_params.cqv);
if (phba->sli4_hba.pc_sli4_params.cqv == LPFC_Q_CREATE_VERSION_2) {
bf_set(lpfc_mbx_cq_create_page_size, &cq_create->u.request,
(PAGE_SIZE/SLI4_PAGE_SIZE));
/* FW only supports 1. Should be PAGE_SIZE/SLI4_PAGE_SIZE */
bf_set(lpfc_mbx_cq_create_page_size, &cq_create->u.request, 1);
bf_set(lpfc_cq_eq_id_2, &cq_create->u.request.context,
eq->queue_id);
} else {
@ -10967,6 +10972,12 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
&rq_create->u.request.context,
hrq->entry_count);
rq_create->u.request.context.buffer_size = LPFC_HDR_BUF_SIZE;
bf_set(lpfc_rq_context_rqe_size,
&rq_create->u.request.context,
LPFC_RQE_SIZE_8);
bf_set(lpfc_rq_context_page_size,
&rq_create->u.request.context,
(PAGE_SIZE/SLI4_PAGE_SIZE));
} else {
switch (hrq->entry_count) {
default:
@ -11042,9 +11053,12 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
phba->sli4_hba.pc_sli4_params.rqv);
if (phba->sli4_hba.pc_sli4_params.rqv == LPFC_Q_CREATE_VERSION_1) {
bf_set(lpfc_rq_context_rqe_count_1,
&rq_create->u.request.context,
hrq->entry_count);
&rq_create->u.request.context, hrq->entry_count);
rq_create->u.request.context.buffer_size = LPFC_DATA_BUF_SIZE;
bf_set(lpfc_rq_context_rqe_size, &rq_create->u.request.context,
LPFC_RQE_SIZE_8);
bf_set(lpfc_rq_context_page_size, &rq_create->u.request.context,
(PAGE_SIZE/SLI4_PAGE_SIZE));
} else {
switch (drq->entry_count) {
default:

View File

@ -18,7 +18,7 @@
* included with this package. *
*******************************************************************/
#define LPFC_DRIVER_VERSION "8.3.22"
#define LPFC_DRIVER_VERSION "8.3.23"
#define LPFC_DRIVER_NAME "lpfc"
#define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp"
#define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp"

View File

@ -1469,8 +1469,8 @@ mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status)
if( scb->state & SCB_ABORT ) {
printk(KERN_WARNING
"megaraid: aborted cmd %lx[%x] complete.\n",
scb->cmd->serial_number, scb->idx);
"megaraid: aborted cmd [%x] complete.\n",
scb->idx);
scb->cmd->result = (DID_ABORT << 16);
@ -1488,8 +1488,8 @@ mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status)
if( scb->state & SCB_RESET ) {
printk(KERN_WARNING
"megaraid: reset cmd %lx[%x] complete.\n",
scb->cmd->serial_number, scb->idx);
"megaraid: reset cmd [%x] complete.\n",
scb->idx);
scb->cmd->result = (DID_RESET << 16);
@ -1958,8 +1958,8 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor)
struct list_head *pos, *next;
scb_t *scb;
printk(KERN_WARNING "megaraid: %s-%lx cmd=%x <c=%d t=%d l=%d>\n",
(aor == SCB_ABORT)? "ABORTING":"RESET", cmd->serial_number,
printk(KERN_WARNING "megaraid: %s cmd=%x <c=%d t=%d l=%d>\n",
(aor == SCB_ABORT)? "ABORTING":"RESET",
cmd->cmnd[0], cmd->device->channel,
cmd->device->id, cmd->device->lun);
@ -1983,9 +1983,9 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor)
if( scb->state & SCB_ISSUED ) {
printk(KERN_WARNING
"megaraid: %s-%lx[%x], fw owner.\n",
"megaraid: %s[%x], fw owner.\n",
(aor==SCB_ABORT) ? "ABORTING":"RESET",
cmd->serial_number, scb->idx);
scb->idx);
return FALSE;
}
@ -1996,9 +1996,9 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor)
* list
*/
printk(KERN_WARNING
"megaraid: %s-%lx[%x], driver owner.\n",
"megaraid: %s-[%x], driver owner.\n",
(aor==SCB_ABORT) ? "ABORTING":"RESET",
cmd->serial_number, scb->idx);
scb->idx);
mega_free_scb(adapter, scb);

View File

@ -2315,8 +2315,8 @@ megaraid_mbox_dpc(unsigned long devp)
// Was an abort issued for this command earlier
if (scb->state & SCB_ABORT) {
con_log(CL_ANN, (KERN_NOTICE
"megaraid: aborted cmd %lx[%x] completed\n",
scp->serial_number, scb->sno));
"megaraid: aborted cmd [%x] completed\n",
scb->sno));
}
/*
@ -2472,8 +2472,8 @@ megaraid_abort_handler(struct scsi_cmnd *scp)
raid_dev = ADAP2RAIDDEV(adapter);
con_log(CL_ANN, (KERN_WARNING
"megaraid: aborting-%ld cmd=%x <c=%d t=%d l=%d>\n",
scp->serial_number, scp->cmnd[0], SCP2CHANNEL(scp),
"megaraid: aborting cmd=%x <c=%d t=%d l=%d>\n",
scp->cmnd[0], SCP2CHANNEL(scp),
SCP2TARGET(scp), SCP2LUN(scp)));
// If FW has stopped responding, simply return failure
@ -2496,9 +2496,8 @@ megaraid_abort_handler(struct scsi_cmnd *scp)
list_del_init(&scb->list); // from completed list
con_log(CL_ANN, (KERN_WARNING
"megaraid: %ld:%d[%d:%d], abort from completed list\n",
scp->serial_number, scb->sno,
scb->dev_channel, scb->dev_target));
"megaraid: %d[%d:%d], abort from completed list\n",
scb->sno, scb->dev_channel, scb->dev_target));
scp->result = (DID_ABORT << 16);
scp->scsi_done(scp);
@ -2527,9 +2526,8 @@ megaraid_abort_handler(struct scsi_cmnd *scp)
ASSERT(!(scb->state & SCB_ISSUED));
con_log(CL_ANN, (KERN_WARNING
"megaraid abort: %ld[%d:%d], driver owner\n",
scp->serial_number, scb->dev_channel,
scb->dev_target));
"megaraid abort: [%d:%d], driver owner\n",
scb->dev_channel, scb->dev_target));
scp->result = (DID_ABORT << 16);
scp->scsi_done(scp);
@ -2560,25 +2558,21 @@ megaraid_abort_handler(struct scsi_cmnd *scp)
if (!(scb->state & SCB_ISSUED)) {
con_log(CL_ANN, (KERN_WARNING
"megaraid abort: %ld%d[%d:%d], invalid state\n",
scp->serial_number, scb->sno, scb->dev_channel,
scb->dev_target));
"megaraid abort: %d[%d:%d], invalid state\n",
scb->sno, scb->dev_channel, scb->dev_target));
BUG();
}
else {
con_log(CL_ANN, (KERN_WARNING
"megaraid abort: %ld:%d[%d:%d], fw owner\n",
scp->serial_number, scb->sno, scb->dev_channel,
scb->dev_target));
"megaraid abort: %d[%d:%d], fw owner\n",
scb->sno, scb->dev_channel, scb->dev_target));
}
}
}
spin_unlock_irq(&adapter->lock);
if (!found) {
con_log(CL_ANN, (KERN_WARNING
"megaraid abort: scsi cmd:%ld, do now own\n",
scp->serial_number));
con_log(CL_ANN, (KERN_WARNING "megaraid abort: do now own\n"));
// FIXME: Should there be a callback for this command?
return SUCCESS;
@ -2649,9 +2643,8 @@ megaraid_reset_handler(struct scsi_cmnd *scp)
} else {
if (scb->scp == scp) { // Found command
con_log(CL_ANN, (KERN_WARNING
"megaraid: %ld:%d[%d:%d], reset from pending list\n",
scp->serial_number, scb->sno,
scb->dev_channel, scb->dev_target));
"megaraid: %d[%d:%d], reset from pending list\n",
scb->sno, scb->dev_channel, scb->dev_target));
} else {
con_log(CL_ANN, (KERN_WARNING
"megaraid: IO packet with %d[%d:%d] being reset\n",

View File

@ -1751,10 +1751,9 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance)
list_del_init(&reset_cmd->list);
if (reset_cmd->scmd) {
reset_cmd->scmd->result = DID_RESET << 16;
printk(KERN_NOTICE "%d:%p reset [%02x], %#lx\n",
printk(KERN_NOTICE "%d:%p reset [%02x]\n",
reset_index, reset_cmd,
reset_cmd->scmd->cmnd[0],
reset_cmd->scmd->serial_number);
reset_cmd->scmd->cmnd[0]);
reset_cmd->scmd->scsi_done(reset_cmd->scmd);
megasas_return_cmd(instance, reset_cmd);
@ -1879,8 +1878,8 @@ static int megasas_generic_reset(struct scsi_cmnd *scmd)
instance = (struct megasas_instance *)scmd->device->host->hostdata;
scmd_printk(KERN_NOTICE, scmd, "megasas: RESET -%ld cmd=%x retries=%x\n",
scmd->serial_number, scmd->cmnd[0], scmd->retries);
scmd_printk(KERN_NOTICE, scmd, "megasas: RESET cmd=%x retries=%x\n",
scmd->cmnd[0], scmd->retries);
if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
printk(KERN_ERR "megasas: cannot recover from previous reset "
@ -2349,9 +2348,9 @@ megasas_issue_pending_cmds_again(struct megasas_instance *instance)
cmd->frame_phys_addr ,
0, instance->reg_set);
} else if (cmd->scmd) {
printk(KERN_NOTICE "megasas: %p scsi cmd [%02x],%#lx"
printk(KERN_NOTICE "megasas: %p scsi cmd [%02x]"
"detected on the internal queue, issue again.\n",
cmd, cmd->scmd->cmnd[0], cmd->scmd->serial_number);
cmd, cmd->scmd->cmnd[0]);
atomic_inc(&instance->fw_outstanding);
instance->instancet->fire_cmd(instance,

View File

@ -415,8 +415,7 @@ static void mesh_start_cmd(struct mesh_state *ms, struct scsi_cmnd *cmd)
#if 1
if (DEBUG_TARGET(cmd)) {
int i;
printk(KERN_DEBUG "mesh_start: %p ser=%lu tgt=%d cmd=",
cmd, cmd->serial_number, id);
printk(KERN_DEBUG "mesh_start: %p tgt=%d cmd=", cmd, id);
for (i = 0; i < cmd->cmd_len; ++i)
printk(" %x", cmd->cmnd[i]);
printk(" use_sg=%d buffer=%p bufflen=%u\n",

View File

@ -522,7 +522,8 @@ _base_display_event_data(struct MPT2SAS_ADAPTER *ioc,
desc = "Device Status Change";
break;
case MPI2_EVENT_IR_OPERATION_STATUS:
desc = "IR Operation Status";
if (!ioc->hide_ir_msg)
desc = "IR Operation Status";
break;
case MPI2_EVENT_SAS_DISCOVERY:
{
@ -553,16 +554,20 @@ _base_display_event_data(struct MPT2SAS_ADAPTER *ioc,
desc = "SAS Enclosure Device Status Change";
break;
case MPI2_EVENT_IR_VOLUME:
desc = "IR Volume";
if (!ioc->hide_ir_msg)
desc = "IR Volume";
break;
case MPI2_EVENT_IR_PHYSICAL_DISK:
desc = "IR Physical Disk";
if (!ioc->hide_ir_msg)
desc = "IR Physical Disk";
break;
case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
desc = "IR Configuration Change List";
if (!ioc->hide_ir_msg)
desc = "IR Configuration Change List";
break;
case MPI2_EVENT_LOG_ENTRY_ADDED:
desc = "Log Entry Added";
if (!ioc->hide_ir_msg)
desc = "Log Entry Added";
break;
}
@ -616,7 +621,10 @@ _base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , u32 log_info)
originator_str = "PL";
break;
case 2:
originator_str = "IR";
if (!ioc->hide_ir_msg)
originator_str = "IR";
else
originator_str = "WarpDrive";
break;
}
@ -1508,6 +1516,7 @@ mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid)
}
ioc->scsi_lookup[i].cb_idx = 0xFF;
ioc->scsi_lookup[i].scmd = NULL;
ioc->scsi_lookup[i].direct_io = 0;
list_add_tail(&ioc->scsi_lookup[i].tracker_list,
&ioc->free_list);
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
@ -1844,10 +1853,12 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
printk("), ");
printk("Capabilities=(");
if (ioc->facts.IOCCapabilities &
MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) {
printk("Raid");
i++;
if (!ioc->hide_ir_msg) {
if (ioc->facts.IOCCapabilities &
MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) {
printk("Raid");
i++;
}
}
if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR) {
@ -3680,6 +3691,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
u32 reply_address;
u16 smid;
struct _tr_list *delayed_tr, *delayed_tr_next;
u8 hide_flag;
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
__func__));
@ -3706,6 +3718,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
ioc->scsi_lookup[i].cb_idx = 0xFF;
ioc->scsi_lookup[i].smid = smid;
ioc->scsi_lookup[i].scmd = NULL;
ioc->scsi_lookup[i].direct_io = 0;
list_add_tail(&ioc->scsi_lookup[i].tracker_list,
&ioc->free_list);
}
@ -3766,6 +3779,15 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
if (sleep_flag == CAN_SLEEP)
_base_static_config_pages(ioc);
if (ioc->wait_for_port_enable_to_complete && ioc->is_warpdrive) {
if (ioc->manu_pg10.OEMIdentifier == 0x80) {
hide_flag = (u8) (ioc->manu_pg10.OEMSpecificFlags0 &
MFG_PAGE10_HIDE_SSDS_MASK);
if (hide_flag != MFG_PAGE10_HIDE_SSDS_MASK)
ioc->mfg_pg10_hide_flag = hide_flag;
}
}
if (ioc->wait_for_port_enable_to_complete) {
if (diag_buffer_enable != 0)
mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable);

View File

@ -69,11 +69,11 @@
#define MPT2SAS_DRIVER_NAME "mpt2sas"
#define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>"
#define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver"
#define MPT2SAS_DRIVER_VERSION "08.100.00.00"
#define MPT2SAS_DRIVER_VERSION "08.100.00.01"
#define MPT2SAS_MAJOR_VERSION 08
#define MPT2SAS_MINOR_VERSION 100
#define MPT2SAS_BUILD_VERSION 00
#define MPT2SAS_RELEASE_VERSION 00
#define MPT2SAS_RELEASE_VERSION 01
/*
* Set MPT2SAS_SG_DEPTH value based on user input.
@ -188,6 +188,16 @@
#define MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_SSDID 0x0044
#define MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID 0x0046
/*
* WarpDrive Specific Log codes
*/
#define MPT2_WARPDRIVE_LOGENTRY (0x8002)
#define MPT2_WARPDRIVE_LC_SSDT (0x41)
#define MPT2_WARPDRIVE_LC_SSDLW (0x43)
#define MPT2_WARPDRIVE_LC_SSDLF (0x44)
#define MPT2_WARPDRIVE_LC_BRMF (0x4D)
/*
* per target private data
*/
@ -199,6 +209,7 @@
* struct MPT2SAS_TARGET - starget private hostdata
* @starget: starget object
* @sas_address: target sas address
* @raid_device: raid_device pointer to access volume data
* @handle: device handle
* @num_luns: number luns
* @flags: MPT_TARGET_FLAGS_XXX flags
@ -208,6 +219,7 @@
struct MPT2SAS_TARGET {
struct scsi_target *starget;
u64 sas_address;
struct _raid_device *raid_device;
u16 handle;
int num_luns;
u32 flags;
@ -215,6 +227,7 @@ struct MPT2SAS_TARGET {
u8 tm_busy;
};
/*
* per device private data
*/
@ -262,6 +275,12 @@ typedef struct _MPI2_CONFIG_PAGE_MAN_10 {
MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_10,
Mpi2ManufacturingPage10_t, MPI2_POINTER pMpi2ManufacturingPage10_t;
#define MFG_PAGE10_HIDE_SSDS_MASK (0x00000003)
#define MFG_PAGE10_HIDE_ALL_DISKS (0x00)
#define MFG_PAGE10_EXPOSE_ALL_DISKS (0x01)
#define MFG_PAGE10_HIDE_IF_VOL_PRESENT (0x02)
struct MPT2SAS_DEVICE {
struct MPT2SAS_TARGET *sas_target;
unsigned int lun;
@ -341,6 +360,7 @@ struct _sas_device {
* @sdev: scsi device struct (volumes are single lun)
* @wwid: unique identifier for the volume
* @handle: device handle
* @block_size: Block size of the volume
* @id: target id
* @channel: target channel
* @volume_type: the raid level
@ -348,20 +368,33 @@ struct _sas_device {
* @num_pds: number of hidden raid components
* @responding: used in _scsih_raid_device_mark_responding
* @percent_complete: resync percent complete
* @direct_io_enabled: Whether direct io to PDs are allowed or not
* @stripe_exponent: X where 2powX is the stripe sz in blocks
* @max_lba: Maximum number of LBA in the volume
* @stripe_sz: Stripe Size of the volume
* @device_info: Device info of the volume member disk
* @pd_handle: Array of handles of the physical drives for direct I/O in le16
*/
#define MPT_MAX_WARPDRIVE_PDS 8
struct _raid_device {
struct list_head list;
struct scsi_target *starget;
struct scsi_device *sdev;
u64 wwid;
u16 handle;
u16 block_sz;
int id;
int channel;
u8 volume_type;
u32 device_info;
u8 num_pds;
u8 responding;
u8 percent_complete;
u8 direct_io_enabled;
u8 stripe_exponent;
u64 max_lba;
u32 stripe_sz;
u32 device_info;
u16 pd_handle[MPT_MAX_WARPDRIVE_PDS];
};
/**
@ -470,6 +503,7 @@ struct chain_tracker {
* @smid: system message id
* @scmd: scsi request pointer
* @cb_idx: callback index
* @direct_io: To indicate whether I/O is direct (WARPDRIVE)
* @chain_list: list of chains associated to this IO
* @tracker_list: list of free request (ioc->free_list)
*/
@ -477,14 +511,14 @@ struct scsiio_tracker {
u16 smid;
struct scsi_cmnd *scmd;
u8 cb_idx;
u8 direct_io;
struct list_head chain_list;
struct list_head tracker_list;
};
/**
* struct request_tracker - misc mf request tracker
* struct request_tracker - firmware request tracker
* @smid: system message id
* @scmd: scsi request pointer
* @cb_idx: callback index
* @tracker_list: list of free request (ioc->free_list)
*/
@ -832,6 +866,11 @@ struct MPT2SAS_ADAPTER {
u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT];
u32 ring_buffer_offset;
u32 ring_buffer_sz;
u8 is_warpdrive;
u8 hide_ir_msg;
u8 mfg_pg10_hide_flag;
u8 hide_drives;
};
typedef u8 (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,

View File

@ -1041,7 +1041,10 @@ _ctl_getiocinfo(void __user *arg)
__func__));
memset(&karg, 0 , sizeof(karg));
karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2;
if (ioc->is_warpdrive)
karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2_SSS6200;
else
karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2;
if (ioc->pfacts)
karg.port_number = ioc->pfacts[0].PortNumber;
pci_read_config_byte(ioc->pdev, PCI_CLASS_REVISION, &revision);

View File

@ -133,6 +133,7 @@ struct mpt2_ioctl_pci_info {
#define MPT2_IOCTL_INTERFACE_FC_IP (0x02)
#define MPT2_IOCTL_INTERFACE_SAS (0x03)
#define MPT2_IOCTL_INTERFACE_SAS2 (0x04)
#define MPT2_IOCTL_INTERFACE_SAS2_SSS6200 (0x05)
#define MPT2_IOCTL_VERSION_LENGTH (32)
/**

View File

@ -233,6 +233,9 @@ static struct pci_device_id scsih_pci_table[] = {
PCI_ANY_ID, PCI_ANY_ID },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3,
PCI_ANY_ID, PCI_ANY_ID },
/* SSS6200 */
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200,
PCI_ANY_ID, PCI_ANY_ID },
{0} /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, scsih_pci_table);
@ -1256,6 +1259,7 @@ _scsih_target_alloc(struct scsi_target *starget)
sas_target_priv_data->handle = raid_device->handle;
sas_target_priv_data->sas_address = raid_device->wwid;
sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME;
sas_target_priv_data->raid_device = raid_device;
raid_device->starget = starget;
}
spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
@ -1455,7 +1459,10 @@ static int
_scsih_is_raid(struct device *dev)
{
struct scsi_device *sdev = to_scsi_device(dev);
struct MPT2SAS_ADAPTER *ioc = shost_priv(sdev->host);
if (ioc->is_warpdrive)
return 0;
return (sdev->channel == RAID_CHANNEL) ? 1 : 0;
}
@ -1480,7 +1487,7 @@ _scsih_get_resync(struct device *dev)
sdev->channel);
spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
if (!raid_device)
if (!raid_device || ioc->is_warpdrive)
goto out;
if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
@ -1640,6 +1647,212 @@ _scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc,
kfree(vol_pg0);
}
/**
* _scsih_disable_ddio - Disable direct I/O for all the volumes
* @ioc: per adapter object
*/
static void
_scsih_disable_ddio(struct MPT2SAS_ADAPTER *ioc)
{
Mpi2RaidVolPage1_t vol_pg1;
Mpi2ConfigReply_t mpi_reply;
struct _raid_device *raid_device;
u16 handle;
u16 ioc_status;
handle = 0xFFFF;
while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
&vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
break;
handle = le16_to_cpu(vol_pg1.DevHandle);
raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
if (raid_device)
raid_device->direct_io_enabled = 0;
}
return;
}
/**
* _scsih_get_num_volumes - Get number of volumes in the ioc
* @ioc: per adapter object
*/
static u8
_scsih_get_num_volumes(struct MPT2SAS_ADAPTER *ioc)
{
Mpi2RaidVolPage1_t vol_pg1;
Mpi2ConfigReply_t mpi_reply;
u16 handle;
u8 vol_cnt = 0;
u16 ioc_status;
handle = 0xFFFF;
while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
&vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
break;
vol_cnt++;
handle = le16_to_cpu(vol_pg1.DevHandle);
}
return vol_cnt;
}
/**
* _scsih_init_warpdrive_properties - Set properties for warpdrive direct I/O.
* @ioc: per adapter object
* @raid_device: the raid_device object
*/
static void
_scsih_init_warpdrive_properties(struct MPT2SAS_ADAPTER *ioc,
struct _raid_device *raid_device)
{
Mpi2RaidVolPage0_t *vol_pg0;
Mpi2RaidPhysDiskPage0_t pd_pg0;
Mpi2ConfigReply_t mpi_reply;
u16 sz;
u8 num_pds, count;
u64 mb = 1024 * 1024;
u64 tb_2 = 2 * mb * mb;
u64 capacity;
u32 stripe_sz;
u8 i, stripe_exp;
if (!ioc->is_warpdrive)
return;
if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS) {
printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
"globally as drives are exposed\n", ioc->name);
return;
}
if (_scsih_get_num_volumes(ioc) > 1) {
_scsih_disable_ddio(ioc);
printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
"globally as number of drives > 1\n", ioc->name);
return;
}
if ((mpt2sas_config_get_number_pds(ioc, raid_device->handle,
&num_pds)) || !num_pds) {
printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
"Failure in computing number of drives\n", ioc->name);
return;
}
sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
sizeof(Mpi2RaidVol0PhysDisk_t));
vol_pg0 = kzalloc(sz, GFP_KERNEL);
if (!vol_pg0) {
printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
"Memory allocation failure for RVPG0\n", ioc->name);
return;
}
if ((mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0,
MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) {
printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
"Failure in retrieving RVPG0\n", ioc->name);
kfree(vol_pg0);
return;
}
/*
* WARPDRIVE:If number of physical disks in a volume exceeds the max pds
* assumed for WARPDRIVE, disable direct I/O
*/
if (num_pds > MPT_MAX_WARPDRIVE_PDS) {
printk(MPT2SAS_WARN_FMT "WarpDrive : Direct IO is disabled "
"for the drive with handle(0x%04x): num_mem=%d, "
"max_mem_allowed=%d\n", ioc->name, raid_device->handle,
num_pds, MPT_MAX_WARPDRIVE_PDS);
kfree(vol_pg0);
return;
}
for (count = 0; count < num_pds; count++) {
if (mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
&pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM,
vol_pg0->PhysDisk[count].PhysDiskNum) ||
pd_pg0.DevHandle == MPT2SAS_INVALID_DEVICE_HANDLE) {
printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is "
"disabled for the drive with handle(0x%04x) member"
"handle retrieval failed for member number=%d\n",
ioc->name, raid_device->handle,
vol_pg0->PhysDisk[count].PhysDiskNum);
goto out_error;
}
raid_device->pd_handle[count] = le16_to_cpu(pd_pg0.DevHandle);
}
/*
* Assumption for WD: Direct I/O is not supported if the volume is
* not RAID0, if the stripe size is not 64KB, if the block size is
* not 512 and if the volume size is >2TB
*/
if (raid_device->volume_type != MPI2_RAID_VOL_TYPE_RAID0 ||
le16_to_cpu(vol_pg0->BlockSize) != 512) {
printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
"for the drive with handle(0x%04x): type=%d, "
"s_sz=%uK, blk_size=%u\n", ioc->name,
raid_device->handle, raid_device->volume_type,
le32_to_cpu(vol_pg0->StripeSize)/2,
le16_to_cpu(vol_pg0->BlockSize));
goto out_error;
}
capacity = (u64) le16_to_cpu(vol_pg0->BlockSize) *
(le64_to_cpu(vol_pg0->MaxLBA) + 1);
if (capacity > tb_2) {
printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
"for the drive with handle(0x%04x) since drive sz > 2TB\n",
ioc->name, raid_device->handle);
goto out_error;
}
stripe_sz = le32_to_cpu(vol_pg0->StripeSize);
stripe_exp = 0;
for (i = 0; i < 32; i++) {
if (stripe_sz & 1)
break;
stripe_exp++;
stripe_sz >>= 1;
}
if (i == 32) {
printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
"for the drive with handle(0x%04x) invalid stripe sz %uK\n",
ioc->name, raid_device->handle,
le32_to_cpu(vol_pg0->StripeSize)/2);
goto out_error;
}
raid_device->stripe_exponent = stripe_exp;
raid_device->direct_io_enabled = 1;
printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is Enabled for the drive"
" with handle(0x%04x)\n", ioc->name, raid_device->handle);
/*
* WARPDRIVE: Though the following fields are not used for direct IO,
* stored for future purpose:
*/
raid_device->max_lba = le64_to_cpu(vol_pg0->MaxLBA);
raid_device->stripe_sz = le32_to_cpu(vol_pg0->StripeSize);
raid_device->block_sz = le16_to_cpu(vol_pg0->BlockSize);
kfree(vol_pg0);
return;
out_error:
raid_device->direct_io_enabled = 0;
for (count = 0; count < num_pds; count++)
raid_device->pd_handle[count] = 0;
kfree(vol_pg0);
return;
}
/**
* _scsih_enable_tlr - setting TLR flags
@ -1710,6 +1923,11 @@ _scsih_slave_configure(struct scsi_device *sdev)
_scsih_get_volume_capabilities(ioc, raid_device);
/*
* WARPDRIVE: Initialize the required data for Direct IO
*/
_scsih_init_warpdrive_properties(ioc, raid_device);
/* RAID Queue Depth Support
* IS volume = underlying qdepth of drive type, either
* MPT2SAS_SAS_QUEUE_DEPTH or MPT2SAS_SATA_QUEUE_DEPTH
@ -1757,14 +1975,16 @@ _scsih_slave_configure(struct scsi_device *sdev)
break;
}
sdev_printk(KERN_INFO, sdev, "%s: "
"handle(0x%04x), wwid(0x%016llx), pd_count(%d), type(%s)\n",
r_level, raid_device->handle,
(unsigned long long)raid_device->wwid,
raid_device->num_pds, ds);
if (!ioc->hide_ir_msg)
sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), "
"wwid(0x%016llx), pd_count(%d), type(%s)\n",
r_level, raid_device->handle,
(unsigned long long)raid_device->wwid,
raid_device->num_pds, ds);
_scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
/* raid transport support */
_scsih_set_level(sdev, raid_device);
if (!ioc->is_warpdrive)
_scsih_set_level(sdev, raid_device);
return 0;
}
@ -2133,8 +2353,7 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
switch (type) {
case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
scmd_lookup = _scsih_scsi_lookup_get(ioc, smid_task);
if (scmd_lookup && (scmd_lookup->serial_number ==
scmd->serial_number))
if (scmd_lookup)
rc = FAILED;
else
rc = SUCCESS;
@ -2182,16 +2401,20 @@ _scsih_tm_display_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd)
struct MPT2SAS_TARGET *priv_target = starget->hostdata;
struct _sas_device *sas_device = NULL;
unsigned long flags;
char *device_str = NULL;
if (!priv_target)
return;
if (ioc->hide_ir_msg)
device_str = "WarpDrive";
else
device_str = "volume";
scsi_print_command(scmd);
if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
starget_printk(KERN_INFO, starget, "volume handle(0x%04x), "
"volume wwid(0x%016llx)\n",
priv_target->handle,
(unsigned long long)priv_target->sas_address);
starget_printk(KERN_INFO, starget, "%s handle(0x%04x), "
"%s wwid(0x%016llx)\n", device_str, priv_target->handle,
device_str, (unsigned long long)priv_target->sas_address);
} else {
spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
@ -3130,6 +3353,9 @@ _scsih_check_ir_config_unhide_events(struct MPT2SAS_ADAPTER *ioc,
a = 0;
b = 0;
if (ioc->is_warpdrive)
return;
/* Volume Resets for Deleted or Removed */
element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
for (i = 0; i < event_data->NumElements; i++, element++) {
@ -3346,6 +3572,105 @@ _scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status)
SAM_STAT_CHECK_CONDITION;
}
/**
* _scsih_scsi_direct_io_get - returns direct io flag
* @ioc: per adapter object
* @smid: system request message index
*
* Returns the smid stored scmd pointer.
*/
static inline u8
_scsih_scsi_direct_io_get(struct MPT2SAS_ADAPTER *ioc, u16 smid)
{
return ioc->scsi_lookup[smid - 1].direct_io;
}
/**
* _scsih_scsi_direct_io_set - sets direct io flag
* @ioc: per adapter object
* @smid: system request message index
* @direct_io: Zero or non-zero value to set in the direct_io flag
*
* Returns Nothing.
*/
static inline void
_scsih_scsi_direct_io_set(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 direct_io)
{
ioc->scsi_lookup[smid - 1].direct_io = direct_io;
}
/**
* _scsih_setup_direct_io - setup MPI request for WARPDRIVE Direct I/O
* @ioc: per adapter object
* @scmd: pointer to scsi command object
* @raid_device: pointer to raid device data structure
* @mpi_request: pointer to the SCSI_IO reqest message frame
* @smid: system request message index
*
* Returns nothing
*/
static void
_scsih_setup_direct_io(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
struct _raid_device *raid_device, Mpi2SCSIIORequest_t *mpi_request,
u16 smid)
{
u32 v_lba, p_lba, stripe_off, stripe_unit, column, io_size;
u32 stripe_sz, stripe_exp;
u8 num_pds, *cdb_ptr, *tmp_ptr, *lba_ptr1, *lba_ptr2;
u8 cdb0 = scmd->cmnd[0];
/*
* Try Direct I/O to RAID memeber disks
*/
if (cdb0 == READ_16 || cdb0 == READ_10 ||
cdb0 == WRITE_16 || cdb0 == WRITE_10) {
cdb_ptr = mpi_request->CDB.CDB32;
if ((cdb0 < READ_16) || !(cdb_ptr[2] | cdb_ptr[3] | cdb_ptr[4]
| cdb_ptr[5])) {
io_size = scsi_bufflen(scmd) >> 9;
/* get virtual lba */
lba_ptr1 = lba_ptr2 = (cdb0 < READ_16) ? &cdb_ptr[2] :
&cdb_ptr[6];
tmp_ptr = (u8 *)&v_lba + 3;
*tmp_ptr-- = *lba_ptr1++;
*tmp_ptr-- = *lba_ptr1++;
*tmp_ptr-- = *lba_ptr1++;
*tmp_ptr = *lba_ptr1;
if (((u64)v_lba + (u64)io_size - 1) <=
(u32)raid_device->max_lba) {
stripe_sz = raid_device->stripe_sz;
stripe_exp = raid_device->stripe_exponent;
stripe_off = v_lba & (stripe_sz - 1);
/* Check whether IO falls within a stripe */
if ((stripe_off + io_size) <= stripe_sz) {
num_pds = raid_device->num_pds;
p_lba = v_lba >> stripe_exp;
stripe_unit = p_lba / num_pds;
column = p_lba % num_pds;
p_lba = (stripe_unit << stripe_exp) +
stripe_off;
mpi_request->DevHandle =
cpu_to_le16(raid_device->
pd_handle[column]);
tmp_ptr = (u8 *)&p_lba + 3;
*lba_ptr2++ = *tmp_ptr--;
*lba_ptr2++ = *tmp_ptr--;
*lba_ptr2++ = *tmp_ptr--;
*lba_ptr2 = *tmp_ptr;
/*
* WD: To indicate this I/O is directI/O
*/
_scsih_scsi_direct_io_set(ioc, smid, 1);
}
}
}
}
}
/**
* _scsih_qcmd - main scsi request entry point
* @scmd: pointer to scsi command object
@ -3363,6 +3688,7 @@ _scsih_qcmd_lck(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
struct MPT2SAS_DEVICE *sas_device_priv_data;
struct MPT2SAS_TARGET *sas_target_priv_data;
struct _raid_device *raid_device;
Mpi2SCSIIORequest_t *mpi_request;
u32 mpi_control;
u16 smid;
@ -3424,8 +3750,10 @@ _scsih_qcmd_lck(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
} else
mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
/* Make sure Device is not raid volume */
if (!_scsih_is_raid(&scmd->device->sdev_gendev) &&
/* Make sure Device is not raid volume.
* We do not expose raid functionality to upper layer for warpdrive.
*/
if (!ioc->is_warpdrive && !_scsih_is_raid(&scmd->device->sdev_gendev) &&
sas_is_tlr_enabled(scmd->device) && scmd->cmd_len != 32)
mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON;
@ -3473,9 +3801,14 @@ _scsih_qcmd_lck(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
}
}
raid_device = sas_target_priv_data->raid_device;
if (raid_device && raid_device->direct_io_enabled)
_scsih_setup_direct_io(ioc, scmd, raid_device, mpi_request,
smid);
if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST))
mpt2sas_base_put_smid_scsi_io(ioc, smid,
sas_device_priv_data->sas_target->handle);
le16_to_cpu(mpi_request->DevHandle));
else
mpt2sas_base_put_smid_default(ioc, smid);
return 0;
@ -3540,10 +3873,16 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
unsigned long flags;
struct scsi_target *starget = scmd->device->sdev_target;
struct MPT2SAS_TARGET *priv_target = starget->hostdata;
char *device_str = NULL;
if (!priv_target)
return;
if (ioc->hide_ir_msg)
device_str = "WarpDrive";
else
device_str = "volume";
if (log_info == 0x31170000)
return;
@ -3660,8 +3999,8 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
scsi_print_command(scmd);
if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
printk(MPT2SAS_WARN_FMT "\tvolume wwid(0x%016llx)\n", ioc->name,
(unsigned long long)priv_target->sas_address);
printk(MPT2SAS_WARN_FMT "\t%s wwid(0x%016llx)\n", ioc->name,
device_str, (unsigned long long)priv_target->sas_address);
} else {
spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
@ -3840,6 +4179,20 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
scmd->result = DID_NO_CONNECT << 16;
goto out;
}
/*
* WARPDRIVE: If direct_io is set then it is directIO,
* the failed direct I/O should be redirected to volume
*/
if (_scsih_scsi_direct_io_get(ioc, smid)) {
_scsih_scsi_direct_io_set(ioc, smid, 0);
memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
mpi_request->DevHandle =
cpu_to_le16(sas_device_priv_data->sas_target->handle);
mpt2sas_base_put_smid_scsi_io(ioc, smid,
sas_device_priv_data->sas_target->handle);
return 0;
}
/* turning off TLR */
scsi_state = mpi_reply->SCSIState;
@ -3848,7 +4201,10 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF;
if (!sas_device_priv_data->tlr_snoop_check) {
sas_device_priv_data->tlr_snoop_check++;
if (!_scsih_is_raid(&scmd->device->sdev_gendev) &&
/* Make sure Device is not raid volume.
* We do not expose raid functionality to upper layer for warpdrive.
*/
if (!ioc->is_warpdrive && !_scsih_is_raid(&scmd->device->sdev_gendev) &&
sas_is_tlr_enabled(scmd->device) &&
response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) {
sas_disable_tlr(scmd->device);
@ -4681,8 +5037,10 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc,
_scsih_ublock_io_device(ioc, sas_device_backup.handle);
mpt2sas_transport_port_remove(ioc, sas_device_backup.sas_address,
sas_device_backup.sas_address_parent);
if (!ioc->hide_drives)
mpt2sas_transport_port_remove(ioc,
sas_device_backup.sas_address,
sas_device_backup.sas_address_parent);
printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), sas_addr"
"(0x%016llx)\n", ioc->name, sas_device_backup.handle,
@ -5413,6 +5771,7 @@ _scsih_sas_pd_hide(struct MPT2SAS_ADAPTER *ioc,
&sas_device->volume_wwid);
set_bit(handle, ioc->pd_handles);
_scsih_reprobe_target(sas_device->starget, 1);
}
/**
@ -5591,7 +5950,8 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc,
Mpi2EventDataIrConfigChangeList_t *event_data = fw_event->event_data;
#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
&& !ioc->hide_ir_msg)
_scsih_sas_ir_config_change_event_debug(ioc, event_data);
#endif
@ -5614,16 +5974,20 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc,
le16_to_cpu(element->VolDevHandle));
break;
case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
_scsih_sas_pd_hide(ioc, element);
if (!ioc->is_warpdrive)
_scsih_sas_pd_hide(ioc, element);
break;
case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
_scsih_sas_pd_expose(ioc, element);
if (!ioc->is_warpdrive)
_scsih_sas_pd_expose(ioc, element);
break;
case MPI2_EVENT_IR_CHANGE_RC_HIDE:
_scsih_sas_pd_add(ioc, element);
if (!ioc->is_warpdrive)
_scsih_sas_pd_add(ioc, element);
break;
case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
_scsih_sas_pd_delete(ioc, element);
if (!ioc->is_warpdrive)
_scsih_sas_pd_delete(ioc, element);
break;
}
}
@ -5654,9 +6018,10 @@ _scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc,
handle = le16_to_cpu(event_data->VolDevHandle);
state = le32_to_cpu(event_data->NewValue);
dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle(0x%04x), "
"old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle,
le32_to_cpu(event_data->PreviousValue), state));
if (!ioc->hide_ir_msg)
dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle(0x%04x), "
"old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle,
le32_to_cpu(event_data->PreviousValue), state));
switch (state) {
case MPI2_RAID_VOL_STATE_MISSING:
@ -5736,9 +6101,10 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc,
handle = le16_to_cpu(event_data->PhysDiskDevHandle);
state = le32_to_cpu(event_data->NewValue);
dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle(0x%04x), "
"old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle,
le32_to_cpu(event_data->PreviousValue), state));
if (!ioc->hide_ir_msg)
dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle(0x%04x), "
"old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle,
le32_to_cpu(event_data->PreviousValue), state));
switch (state) {
case MPI2_RAID_PD_STATE_ONLINE:
@ -5747,7 +6113,8 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc,
case MPI2_RAID_PD_STATE_OPTIMAL:
case MPI2_RAID_PD_STATE_HOT_SPARE:
set_bit(handle, ioc->pd_handles);
if (!ioc->is_warpdrive)
set_bit(handle, ioc->pd_handles);
spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
@ -5851,7 +6218,8 @@ _scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc,
u16 handle;
#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
&& !ioc->hide_ir_msg)
_scsih_sas_ir_operation_status_event_debug(ioc,
event_data);
#endif
@ -5910,7 +6278,7 @@ static void
_scsih_mark_responding_sas_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
u16 slot, u16 handle)
{
struct MPT2SAS_TARGET *sas_target_priv_data;
struct MPT2SAS_TARGET *sas_target_priv_data = NULL;
struct scsi_target *starget;
struct _sas_device *sas_device;
unsigned long flags;
@ -5918,7 +6286,7 @@ _scsih_mark_responding_sas_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
spin_lock_irqsave(&ioc->sas_device_lock, flags);
list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
if (sas_device->sas_address == sas_address &&
sas_device->slot == slot && sas_device->starget) {
sas_device->slot == slot) {
sas_device->responding = 1;
starget = sas_device->starget;
if (starget && starget->hostdata) {
@ -5927,13 +6295,15 @@ _scsih_mark_responding_sas_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
sas_target_priv_data->deleted = 0;
} else
sas_target_priv_data = NULL;
starget_printk(KERN_INFO, sas_device->starget,
"handle(0x%04x), sas_addr(0x%016llx), enclosure "
"logical id(0x%016llx), slot(%d)\n", handle,
(unsigned long long)sas_device->sas_address,
(unsigned long long)
sas_device->enclosure_logical_id,
sas_device->slot);
if (starget)
starget_printk(KERN_INFO, starget,
"handle(0x%04x), sas_addr(0x%016llx), "
"enclosure logical id(0x%016llx), "
"slot(%d)\n", handle,
(unsigned long long)sas_device->sas_address,
(unsigned long long)
sas_device->enclosure_logical_id,
sas_device->slot);
if (sas_device->handle == handle)
goto out;
printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n",
@ -6025,6 +6395,12 @@ _scsih_mark_responding_raid_device(struct MPT2SAS_ADAPTER *ioc, u64 wwid,
starget_printk(KERN_INFO, raid_device->starget,
"handle(0x%04x), wwid(0x%016llx)\n", handle,
(unsigned long long)raid_device->wwid);
/*
* WARPDRIVE: The handles of the PDs might have changed
* across the host reset so re-initialize the
* required data for Direct IO
*/
_scsih_init_warpdrive_properties(ioc, raid_device);
if (raid_device->handle == handle)
goto out;
printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n",
@ -6086,18 +6462,20 @@ _scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc)
}
/* refresh the pd_handles */
phys_disk_num = 0xFF;
memset(ioc->pd_handles, 0, ioc->pd_handles_sz);
while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
&pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
phys_disk_num))) {
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
break;
phys_disk_num = pd_pg0.PhysDiskNum;
handle = le16_to_cpu(pd_pg0.DevHandle);
set_bit(handle, ioc->pd_handles);
if (!ioc->is_warpdrive) {
phys_disk_num = 0xFF;
memset(ioc->pd_handles, 0, ioc->pd_handles_sz);
while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
&pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
phys_disk_num))) {
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
break;
phys_disk_num = pd_pg0.PhysDiskNum;
handle = le16_to_cpu(pd_pg0.DevHandle);
set_bit(handle, ioc->pd_handles);
}
}
}
@ -6242,6 +6620,50 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
}
}
/**
* _scsih_hide_unhide_sas_devices - add/remove device to/from OS
* @ioc: per adapter object
*
* Return nothing.
*/
static void
_scsih_hide_unhide_sas_devices(struct MPT2SAS_ADAPTER *ioc)
{
struct _sas_device *sas_device, *sas_device_next;
if (!ioc->is_warpdrive || ioc->mfg_pg10_hide_flag !=
MFG_PAGE10_HIDE_IF_VOL_PRESENT)
return;
if (ioc->hide_drives) {
if (_scsih_get_num_volumes(ioc))
return;
ioc->hide_drives = 0;
list_for_each_entry_safe(sas_device, sas_device_next,
&ioc->sas_device_list, list) {
if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
sas_device->sas_address_parent)) {
_scsih_sas_device_remove(ioc, sas_device);
} else if (!sas_device->starget) {
mpt2sas_transport_port_remove(ioc,
sas_device->sas_address,
sas_device->sas_address_parent);
_scsih_sas_device_remove(ioc, sas_device);
}
}
} else {
if (!_scsih_get_num_volumes(ioc))
return;
ioc->hide_drives = 1;
list_for_each_entry_safe(sas_device, sas_device_next,
&ioc->sas_device_list, list) {
mpt2sas_transport_port_remove(ioc,
sas_device->sas_address,
sas_device->sas_address_parent);
}
}
}
/**
* mpt2sas_scsih_reset_handler - reset callback handler (for scsih)
* @ioc: per adapter object
@ -6326,6 +6748,7 @@ _firmware_event_work(struct work_struct *work)
spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock,
flags);
_scsih_remove_unresponding_sas_devices(ioc);
_scsih_hide_unhide_sas_devices(ioc);
return;
}
@ -6425,6 +6848,53 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
(Mpi2EventDataIrVolume_t *)
mpi_reply->EventData);
break;
case MPI2_EVENT_LOG_ENTRY_ADDED:
{
Mpi2EventDataLogEntryAdded_t *log_entry;
u32 *log_code;
if (!ioc->is_warpdrive)
break;
log_entry = (Mpi2EventDataLogEntryAdded_t *)
mpi_reply->EventData;
log_code = (u32 *)log_entry->LogData;
if (le16_to_cpu(log_entry->LogEntryQualifier)
!= MPT2_WARPDRIVE_LOGENTRY)
break;
switch (le32_to_cpu(*log_code)) {
case MPT2_WARPDRIVE_LC_SSDT:
printk(MPT2SAS_WARN_FMT "WarpDrive Warning: "
"IO Throttling has occurred in the WarpDrive "
"subsystem. Check WarpDrive documentation for "
"additional details.\n", ioc->name);
break;
case MPT2_WARPDRIVE_LC_SSDLW:
printk(MPT2SAS_WARN_FMT "WarpDrive Warning: "
"Program/Erase Cycles for the WarpDrive subsystem "
"in degraded range. Check WarpDrive documentation "
"for additional details.\n", ioc->name);
break;
case MPT2_WARPDRIVE_LC_SSDLF:
printk(MPT2SAS_ERR_FMT "WarpDrive Fatal Error: "
"There are no Program/Erase Cycles for the "
"WarpDrive subsystem. The storage device will be "
"in read-only mode. Check WarpDrive documentation "
"for additional details.\n", ioc->name);
break;
case MPT2_WARPDRIVE_LC_BRMF:
printk(MPT2SAS_ERR_FMT "WarpDrive Fatal Error: "
"The Backup Rail Monitor has failed on the "
"WarpDrive subsystem. Check WarpDrive "
"documentation for additional details.\n",
ioc->name);
break;
}
break;
}
case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
case MPI2_EVENT_IR_OPERATION_STATUS:
case MPI2_EVENT_SAS_DISCOVERY:
@ -6583,7 +7053,8 @@ _scsih_ir_shutdown(struct MPT2SAS_ADAPTER *ioc)
mpi_request->Function = MPI2_FUNCTION_RAID_ACTION;
mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
printk(MPT2SAS_INFO_FMT "IR shutdown (sending)\n", ioc->name);
if (!ioc->hide_ir_msg)
printk(MPT2SAS_INFO_FMT "IR shutdown (sending)\n", ioc->name);
init_completion(&ioc->scsih_cmds.done);
mpt2sas_base_put_smid_default(ioc, smid);
wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
@ -6597,10 +7068,11 @@ _scsih_ir_shutdown(struct MPT2SAS_ADAPTER *ioc)
if (ioc->scsih_cmds.status & MPT2_CMD_REPLY_VALID) {
mpi_reply = ioc->scsih_cmds.reply;
printk(MPT2SAS_INFO_FMT "IR shutdown (complete): "
"ioc_status(0x%04x), loginfo(0x%08x)\n",
ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
le32_to_cpu(mpi_reply->IOCLogInfo));
if (!ioc->hide_ir_msg)
printk(MPT2SAS_INFO_FMT "IR shutdown (complete): "
"ioc_status(0x%04x), loginfo(0x%08x)\n",
ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
le32_to_cpu(mpi_reply->IOCLogInfo));
}
out:
@ -6759,6 +7231,9 @@ _scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc)
spin_lock_irqsave(&ioc->sas_device_lock, flags);
list_move_tail(&sas_device->list, &ioc->sas_device_list);
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
if (ioc->hide_drives)
return;
if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
sas_device->sas_address_parent)) {
_scsih_sas_device_remove(ioc, sas_device);
@ -6812,6 +7287,9 @@ _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc)
list_move_tail(&sas_device->list, &ioc->sas_device_list);
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
if (ioc->hide_drives)
continue;
if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
sas_device->sas_address_parent)) {
_scsih_sas_device_remove(ioc, sas_device);
@ -6882,6 +7360,11 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->id = mpt_ids++;
sprintf(ioc->name, "%s%d", MPT2SAS_DRIVER_NAME, ioc->id);
ioc->pdev = pdev;
if (id->device == MPI2_MFGPAGE_DEVID_SSS6200) {
ioc->is_warpdrive = 1;
ioc->hide_ir_msg = 1;
} else
ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS;
ioc->scsi_io_cb_idx = scsi_io_cb_idx;
ioc->tm_cb_idx = tm_cb_idx;
ioc->ctl_cb_idx = ctl_cb_idx;
@ -6947,6 +7430,20 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
ioc->wait_for_port_enable_to_complete = 0;
if (ioc->is_warpdrive) {
if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS)
ioc->hide_drives = 0;
else if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_HIDE_ALL_DISKS)
ioc->hide_drives = 1;
else {
if (_scsih_get_num_volumes(ioc))
ioc->hide_drives = 1;
else
ioc->hide_drives = 0;
}
} else
ioc->hide_drives = 0;
_scsih_probe_devices(ioc);
return 0;

View File

@ -3,6 +3,7 @@
#
# Copyright 2007 Red Hat, Inc.
# Copyright 2008 Marvell. <kewei@marvell.com>
# Copyright 2009-20011 Marvell. <yuxiangl@marvell.com>
#
# This file is licensed under GPLv2.
#

View File

@ -3,6 +3,7 @@
#
# Copyright 2007 Red Hat, Inc.
# Copyright 2008 Marvell. <kewei@marvell.com>
# Copyright 2009-2011 Marvell. <yuxiangl@marvell.com>
#
# This file is licensed under GPLv2.
#

View File

@ -3,6 +3,7 @@
*
* Copyright 2007 Red Hat, Inc.
* Copyright 2008 Marvell. <kewei@marvell.com>
* Copyright 2009-2011 Marvell. <yuxiangl@marvell.com>
*
* This file is licensed under GPLv2.
*

View File

@ -3,6 +3,7 @@
*
* Copyright 2007 Red Hat, Inc.
* Copyright 2008 Marvell. <kewei@marvell.com>
* Copyright 2009-2011 Marvell. <yuxiangl@marvell.com>
*
* This file is licensed under GPLv2.
*

View File

@ -3,6 +3,7 @@
*
* Copyright 2007 Red Hat, Inc.
* Copyright 2008 Marvell. <kewei@marvell.com>
* Copyright 2009-2011 Marvell. <yuxiangl@marvell.com>
*
* This file is licensed under GPLv2.
*

View File

@ -3,6 +3,7 @@
*
* Copyright 2007 Red Hat, Inc.
* Copyright 2008 Marvell. <kewei@marvell.com>
* Copyright 2009-2011 Marvell. <yuxiangl@marvell.com>
*
* This file is licensed under GPLv2.
*

View File

@ -3,6 +3,7 @@
*
* Copyright 2007 Red Hat, Inc.
* Copyright 2008 Marvell. <kewei@marvell.com>
* Copyright 2009-2011 Marvell. <yuxiangl@marvell.com>
*
* This file is licensed under GPLv2.
*

View File

@ -3,6 +3,7 @@
*
* Copyright 2007 Red Hat, Inc.
* Copyright 2008 Marvell. <kewei@marvell.com>
* Copyright 2009-2011 Marvell. <yuxiangl@marvell.com>
*
* This file is licensed under GPLv2.
*
@ -34,6 +35,8 @@ enum chip_flavors {
chip_6485,
chip_9480,
chip_9180,
chip_9445,
chip_9485,
chip_1300,
chip_1320
};

View File

@ -3,6 +3,7 @@
*
* Copyright 2007 Red Hat, Inc.
* Copyright 2008 Marvell. <kewei@marvell.com>
* Copyright 2009-2011 Marvell. <yuxiangl@marvell.com>
*
* This file is licensed under GPLv2.
*
@ -25,13 +26,24 @@
#include "mv_sas.h"
static int lldd_max_execute_num = 1;
module_param_named(collector, lldd_max_execute_num, int, S_IRUGO);
MODULE_PARM_DESC(collector, "\n"
"\tIf greater than one, tells the SAS Layer to run in Task Collector\n"
"\tMode. If 1 or 0, tells the SAS Layer to run in Direct Mode.\n"
"\tThe mvsas SAS LLDD supports both modes.\n"
"\tDefault: 1 (Direct Mode).\n");
static struct scsi_transport_template *mvs_stt;
struct kmem_cache *mvs_task_list_cache;
static const struct mvs_chip_info mvs_chips[] = {
[chip_6320] = { 1, 2, 0x400, 17, 16, 9, &mvs_64xx_dispatch, },
[chip_6440] = { 1, 4, 0x400, 17, 16, 9, &mvs_64xx_dispatch, },
[chip_6485] = { 1, 8, 0x800, 33, 32, 10, &mvs_64xx_dispatch, },
[chip_9180] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, },
[chip_9480] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, },
[chip_9445] = { 1, 4, 0x800, 17, 64, 11, &mvs_94xx_dispatch, },
[chip_9485] = { 2, 4, 0x800, 17, 64, 11, &mvs_94xx_dispatch, },
[chip_1300] = { 1, 4, 0x400, 17, 16, 9, &mvs_64xx_dispatch, },
[chip_1320] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, },
};
@ -107,7 +119,6 @@ static void __devinit mvs_phy_init(struct mvs_info *mvi, int phy_id)
static void mvs_free(struct mvs_info *mvi)
{
int i;
struct mvs_wq *mwq;
int slot_nr;
@ -119,12 +130,8 @@ static void mvs_free(struct mvs_info *mvi)
else
slot_nr = MVS_SLOTS;
for (i = 0; i < mvi->tags_num; i++) {
struct mvs_slot_info *slot = &mvi->slot_info[i];
if (slot->buf)
dma_free_coherent(mvi->dev, MVS_SLOT_BUF_SZ,
slot->buf, slot->buf_dma);
}
if (mvi->dma_pool)
pci_pool_destroy(mvi->dma_pool);
if (mvi->tx)
dma_free_coherent(mvi->dev,
@ -213,6 +220,7 @@ static irqreturn_t mvs_interrupt(int irq, void *opaque)
static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
{
int i = 0, slot_nr;
char pool_name[32];
if (mvi->flags & MVF_FLAG_SOC)
slot_nr = MVS_SOC_SLOTS;
@ -272,18 +280,14 @@ static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
if (!mvi->bulk_buffer)
goto err_out;
#endif
for (i = 0; i < slot_nr; i++) {
struct mvs_slot_info *slot = &mvi->slot_info[i];
slot->buf = dma_alloc_coherent(mvi->dev, MVS_SLOT_BUF_SZ,
&slot->buf_dma, GFP_KERNEL);
if (!slot->buf) {
printk(KERN_DEBUG"failed to allocate slot->buf.\n");
sprintf(pool_name, "%s%d", "mvs_dma_pool", mvi->id);
mvi->dma_pool = pci_pool_create(pool_name, mvi->pdev, MVS_SLOT_BUF_SZ, 16, 0);
if (!mvi->dma_pool) {
printk(KERN_DEBUG "failed to create dma pool %s.\n", pool_name);
goto err_out;
}
memset(slot->buf, 0, MVS_SLOT_BUF_SZ);
++mvi->tags_num;
}
mvi->tags_num = slot_nr;
/* Initialize tags */
mvs_tag_init(mvi);
return 0;
@ -484,7 +488,7 @@ static void __devinit mvs_post_sas_ha_init(struct Scsi_Host *shost,
sha->num_phys = nr_core * chip_info->n_phy;
sha->lldd_max_execute_num = 1;
sha->lldd_max_execute_num = lldd_max_execute_num;
if (mvi->flags & MVF_FLAG_SOC)
can_queue = MVS_SOC_CAN_QUEUE;
@ -670,6 +674,24 @@ static struct pci_device_id __devinitdata mvs_pci_table[] = {
{ PCI_VDEVICE(TTI, 0x2740), chip_9480 },
{ PCI_VDEVICE(TTI, 0x2744), chip_9480 },
{ PCI_VDEVICE(TTI, 0x2760), chip_9480 },
{
.vendor = 0x1b4b,
.device = 0x9445,
.subvendor = PCI_ANY_ID,
.subdevice = 0x9480,
.class = 0,
.class_mask = 0,
.driver_data = chip_9445,
},
{
.vendor = 0x1b4b,
.device = 0x9485,
.subvendor = PCI_ANY_ID,
.subdevice = 0x9480,
.class = 0,
.class_mask = 0,
.driver_data = chip_9485,
},
{ } /* terminate list */
};
@ -690,6 +712,14 @@ static int __init mvs_init(void)
if (!mvs_stt)
return -ENOMEM;
mvs_task_list_cache = kmem_cache_create("mvs_task_list", sizeof(struct mvs_task_list),
0, SLAB_HWCACHE_ALIGN, NULL);
if (!mvs_task_list_cache) {
rc = -ENOMEM;
mv_printk("%s: mvs_task_list_cache alloc failed! \n", __func__);
goto err_out;
}
rc = pci_register_driver(&mvs_pci_driver);
if (rc)
@ -706,6 +736,7 @@ static void __exit mvs_exit(void)
{
pci_unregister_driver(&mvs_pci_driver);
sas_release_transport(mvs_stt);
kmem_cache_destroy(mvs_task_list_cache);
}
module_init(mvs_init);

View File

@ -3,6 +3,7 @@
*
* Copyright 2007 Red Hat, Inc.
* Copyright 2008 Marvell. <kewei@marvell.com>
* Copyright 2009-2011 Marvell. <yuxiangl@marvell.com>
*
* This file is licensed under GPLv2.
*
@ -862,178 +863,286 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi,
}
#define DEV_IS_GONE(mvi_dev) ((!mvi_dev || (mvi_dev->dev_type == NO_DEVICE)))
static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
struct completion *completion,int is_tmf,
struct mvs_tmf_task *tmf)
static int mvs_task_prep(struct sas_task *task, struct mvs_info *mvi, int is_tmf,
struct mvs_tmf_task *tmf, int *pass)
{
struct domain_device *dev = task->dev;
struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev;
struct mvs_info *mvi = mvi_dev->mvi_info;
struct mvs_device *mvi_dev = dev->lldd_dev;
struct mvs_task_exec_info tei;
struct sas_task *t = task;
struct mvs_slot_info *slot;
u32 tag = 0xdeadbeef, rc, n_elem = 0;
u32 n = num, pass = 0;
unsigned long flags = 0, flags_libsas = 0;
u32 tag = 0xdeadbeef, n_elem = 0;
int rc = 0;
if (!dev->port) {
struct task_status_struct *tsm = &t->task_status;
struct task_status_struct *tsm = &task->task_status;
tsm->resp = SAS_TASK_UNDELIVERED;
tsm->stat = SAS_PHY_DOWN;
/*
* libsas will use dev->port, should
* not call task_done for sata
*/
if (dev->dev_type != SATA_DEV)
t->task_done(t);
return 0;
task->task_done(task);
return rc;
}
spin_lock_irqsave(&mvi->lock, flags);
do {
dev = t->dev;
mvi_dev = dev->lldd_dev;
if (DEV_IS_GONE(mvi_dev)) {
if (mvi_dev)
mv_dprintk("device %d not ready.\n",
mvi_dev->device_id);
else
mv_dprintk("device %016llx not ready.\n",
SAS_ADDR(dev->sas_addr));
if (DEV_IS_GONE(mvi_dev)) {
if (mvi_dev)
mv_dprintk("device %d not ready.\n",
mvi_dev->device_id);
else
mv_dprintk("device %016llx not ready.\n",
SAS_ADDR(dev->sas_addr));
rc = SAS_PHY_DOWN;
goto out_done;
}
return rc;
}
tei.port = dev->port->lldd_port;
if (tei.port && !tei.port->port_attached && !tmf) {
if (sas_protocol_ata(task->task_proto)) {
struct task_status_struct *ts = &task->task_status;
mv_dprintk("SATA/STP port %d does not attach"
"device.\n", dev->port->id);
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_PHY_DOWN;
if (dev->port->id >= mvi->chip->n_phy)
tei.port = &mvi->port[dev->port->id - mvi->chip->n_phy];
else
tei.port = &mvi->port[dev->port->id];
task->task_done(task);
if (tei.port && !tei.port->port_attached) {
if (sas_protocol_ata(t->task_proto)) {
struct task_status_struct *ts = &t->task_status;
mv_dprintk("port %d does not"
"attached device.\n", dev->port->id);
ts->stat = SAS_PROTO_RESPONSE;
ts->stat = SAS_PHY_DOWN;
spin_unlock_irqrestore(dev->sata_dev.ap->lock,
flags_libsas);
spin_unlock_irqrestore(&mvi->lock, flags);
t->task_done(t);
spin_lock_irqsave(&mvi->lock, flags);
spin_lock_irqsave(dev->sata_dev.ap->lock,
flags_libsas);
if (n > 1)
t = list_entry(t->list.next,
struct sas_task, list);
continue;
} else {
struct task_status_struct *ts = &t->task_status;
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_PHY_DOWN;
t->task_done(t);
if (n > 1)
t = list_entry(t->list.next,
struct sas_task, list);
continue;
}
}
if (!sas_protocol_ata(t->task_proto)) {
if (t->num_scatter) {
n_elem = dma_map_sg(mvi->dev,
t->scatter,
t->num_scatter,
t->data_dir);
if (!n_elem) {
rc = -ENOMEM;
goto err_out;
}
}
} else {
n_elem = t->num_scatter;
struct task_status_struct *ts = &task->task_status;
mv_dprintk("SAS port %d does not attach"
"device.\n", dev->port->id);
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_PHY_DOWN;
task->task_done(task);
}
return rc;
}
rc = mvs_tag_alloc(mvi, &tag);
if (rc)
goto err_out;
slot = &mvi->slot_info[tag];
t->lldd_task = NULL;
slot->n_elem = n_elem;
slot->slot_tag = tag;
memset(slot->buf, 0, MVS_SLOT_BUF_SZ);
tei.task = t;
tei.hdr = &mvi->slot[tag];
tei.tag = tag;
tei.n_elem = n_elem;
switch (t->task_proto) {
case SAS_PROTOCOL_SMP:
rc = mvs_task_prep_smp(mvi, &tei);
break;
case SAS_PROTOCOL_SSP:
rc = mvs_task_prep_ssp(mvi, &tei, is_tmf, tmf);
break;
case SAS_PROTOCOL_SATA:
case SAS_PROTOCOL_STP:
case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
rc = mvs_task_prep_ata(mvi, &tei);
break;
default:
dev_printk(KERN_ERR, mvi->dev,
"unknown sas_task proto: 0x%x\n",
t->task_proto);
rc = -EINVAL;
break;
if (!sas_protocol_ata(task->task_proto)) {
if (task->num_scatter) {
n_elem = dma_map_sg(mvi->dev,
task->scatter,
task->num_scatter,
task->data_dir);
if (!n_elem) {
rc = -ENOMEM;
goto prep_out;
}
}
} else {
n_elem = task->num_scatter;
}
if (rc) {
mv_dprintk("rc is %x\n", rc);
goto err_out_tag;
}
slot->task = t;
slot->port = tei.port;
t->lldd_task = slot;
list_add_tail(&slot->entry, &tei.port->list);
/* TODO: select normal or high priority */
spin_lock(&t->task_state_lock);
t->task_state_flags |= SAS_TASK_AT_INITIATOR;
spin_unlock(&t->task_state_lock);
rc = mvs_tag_alloc(mvi, &tag);
if (rc)
goto err_out;
mvs_hba_memory_dump(mvi, tag, t->task_proto);
mvi_dev->running_req++;
++pass;
mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1);
if (n > 1)
t = list_entry(t->list.next, struct sas_task, list);
if (likely(pass))
MVS_CHIP_DISP->start_delivery(mvi, (mvi->tx_prod - 1) &
(MVS_CHIP_SLOT_SZ - 1));
slot = &mvi->slot_info[tag];
} while (--n);
rc = 0;
goto out_done;
task->lldd_task = NULL;
slot->n_elem = n_elem;
slot->slot_tag = tag;
slot->buf = pci_pool_alloc(mvi->dma_pool, GFP_ATOMIC, &slot->buf_dma);
if (!slot->buf)
goto err_out_tag;
memset(slot->buf, 0, MVS_SLOT_BUF_SZ);
tei.task = task;
tei.hdr = &mvi->slot[tag];
tei.tag = tag;
tei.n_elem = n_elem;
switch (task->task_proto) {
case SAS_PROTOCOL_SMP:
rc = mvs_task_prep_smp(mvi, &tei);
break;
case SAS_PROTOCOL_SSP:
rc = mvs_task_prep_ssp(mvi, &tei, is_tmf, tmf);
break;
case SAS_PROTOCOL_SATA:
case SAS_PROTOCOL_STP:
case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
rc = mvs_task_prep_ata(mvi, &tei);
break;
default:
dev_printk(KERN_ERR, mvi->dev,
"unknown sas_task proto: 0x%x\n",
task->task_proto);
rc = -EINVAL;
break;
}
if (rc) {
mv_dprintk("rc is %x\n", rc);
goto err_out_slot_buf;
}
slot->task = task;
slot->port = tei.port;
task->lldd_task = slot;
list_add_tail(&slot->entry, &tei.port->list);
spin_lock(&task->task_state_lock);
task->task_state_flags |= SAS_TASK_AT_INITIATOR;
spin_unlock(&task->task_state_lock);
mvs_hba_memory_dump(mvi, tag, task->task_proto);
mvi_dev->running_req++;
++(*pass);
mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1);
return rc;
err_out_slot_buf:
pci_pool_free(mvi->dma_pool, slot->buf, slot->buf_dma);
err_out_tag:
mvs_tag_free(mvi, tag);
err_out:
dev_printk(KERN_ERR, mvi->dev, "mvsas exec failed[%d]!\n", rc);
if (!sas_protocol_ata(t->task_proto))
dev_printk(KERN_ERR, mvi->dev, "mvsas prep failed[%d]!\n", rc);
if (!sas_protocol_ata(task->task_proto))
if (n_elem)
dma_unmap_sg(mvi->dev, t->scatter, n_elem,
t->data_dir);
out_done:
dma_unmap_sg(mvi->dev, task->scatter, n_elem,
task->data_dir);
prep_out:
return rc;
}
static struct mvs_task_list *mvs_task_alloc_list(int *num, gfp_t gfp_flags)
{
struct mvs_task_list *first = NULL;
for (; *num > 0; --*num) {
struct mvs_task_list *mvs_list = kmem_cache_zalloc(mvs_task_list_cache, gfp_flags);
if (!mvs_list)
break;
INIT_LIST_HEAD(&mvs_list->list);
if (!first)
first = mvs_list;
else
list_add_tail(&mvs_list->list, &first->list);
}
return first;
}
static inline void mvs_task_free_list(struct mvs_task_list *mvs_list)
{
LIST_HEAD(list);
struct list_head *pos, *a;
struct mvs_task_list *mlist = NULL;
__list_add(&list, mvs_list->list.prev, &mvs_list->list);
list_for_each_safe(pos, a, &list) {
list_del_init(pos);
mlist = list_entry(pos, struct mvs_task_list, list);
kmem_cache_free(mvs_task_list_cache, mlist);
}
}
static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
struct completion *completion, int is_tmf,
struct mvs_tmf_task *tmf)
{
struct domain_device *dev = task->dev;
struct mvs_info *mvi = NULL;
u32 rc = 0;
u32 pass = 0;
unsigned long flags = 0;
mvi = ((struct mvs_device *)task->dev->lldd_dev)->mvi_info;
if ((dev->dev_type == SATA_DEV) && (dev->sata_dev.ap != NULL))
spin_unlock_irq(dev->sata_dev.ap->lock);
spin_lock_irqsave(&mvi->lock, flags);
rc = mvs_task_prep(task, mvi, is_tmf, tmf, &pass);
if (rc)
dev_printk(KERN_ERR, mvi->dev, "mvsas exec failed[%d]!\n", rc);
if (likely(pass))
MVS_CHIP_DISP->start_delivery(mvi, (mvi->tx_prod - 1) &
(MVS_CHIP_SLOT_SZ - 1));
spin_unlock_irqrestore(&mvi->lock, flags);
if ((dev->dev_type == SATA_DEV) && (dev->sata_dev.ap != NULL))
spin_lock_irq(dev->sata_dev.ap->lock);
return rc;
}
static int mvs_collector_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
struct completion *completion, int is_tmf,
struct mvs_tmf_task *tmf)
{
struct domain_device *dev = task->dev;
struct mvs_prv_info *mpi = dev->port->ha->lldd_ha;
struct mvs_info *mvi = NULL;
struct sas_task *t = task;
struct mvs_task_list *mvs_list = NULL, *a;
LIST_HEAD(q);
int pass[2] = {0};
u32 rc = 0;
u32 n = num;
unsigned long flags = 0;
mvs_list = mvs_task_alloc_list(&n, gfp_flags);
if (n) {
printk(KERN_ERR "%s: mvs alloc list failed.\n", __func__);
rc = -ENOMEM;
goto free_list;
}
__list_add(&q, mvs_list->list.prev, &mvs_list->list);
list_for_each_entry(a, &q, list) {
a->task = t;
t = list_entry(t->list.next, struct sas_task, list);
}
list_for_each_entry(a, &q , list) {
t = a->task;
mvi = ((struct mvs_device *)t->dev->lldd_dev)->mvi_info;
spin_lock_irqsave(&mvi->lock, flags);
rc = mvs_task_prep(t, mvi, is_tmf, tmf, &pass[mvi->id]);
if (rc)
dev_printk(KERN_ERR, mvi->dev, "mvsas exec failed[%d]!\n", rc);
spin_unlock_irqrestore(&mvi->lock, flags);
}
if (likely(pass[0]))
MVS_CHIP_DISP->start_delivery(mpi->mvi[0],
(mpi->mvi[0]->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1));
if (likely(pass[1]))
MVS_CHIP_DISP->start_delivery(mpi->mvi[1],
(mpi->mvi[1]->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1));
list_del_init(&q);
free_list:
if (mvs_list)
mvs_task_free_list(mvs_list);
return rc;
}
int mvs_queue_command(struct sas_task *task, const int num,
gfp_t gfp_flags)
{
return mvs_task_exec(task, num, gfp_flags, NULL, 0, NULL);
struct mvs_device *mvi_dev = task->dev->lldd_dev;
struct sas_ha_struct *sas = mvi_dev->mvi_info->sas;
if (sas->lldd_max_execute_num < 2)
return mvs_task_exec(task, num, gfp_flags, NULL, 0, NULL);
else
return mvs_collector_task_exec(task, num, gfp_flags, NULL, 0, NULL);
}
static void mvs_slot_free(struct mvs_info *mvi, u32 rx_desc)
@ -1067,6 +1176,11 @@ static void mvs_slot_task_free(struct mvs_info *mvi, struct sas_task *task,
/* do nothing */
break;
}
if (slot->buf) {
pci_pool_free(mvi->dma_pool, slot->buf, slot->buf_dma);
slot->buf = NULL;
}
list_del_init(&slot->entry);
task->lldd_task = NULL;
slot->task = NULL;
@ -1255,6 +1369,7 @@ static void mvs_port_notify_formed(struct asd_sas_phy *sas_phy, int lock)
spin_lock_irqsave(&mvi->lock, flags);
port->port_attached = 1;
phy->port = port;
sas_port->lldd_port = port;
if (phy->phy_type & PORT_TYPE_SAS) {
port->wide_port_phymap = sas_port->phy_mask;
mv_printk("set wide port phy map %x\n", sas_port->phy_mask);

View File

@ -3,6 +3,7 @@
*
* Copyright 2007 Red Hat, Inc.
* Copyright 2008 Marvell. <kewei@marvell.com>
* Copyright 2009-2011 Marvell. <yuxiangl@marvell.com>
*
* This file is licensed under GPLv2.
*
@ -67,6 +68,7 @@ extern struct mvs_tgt_initiator mvs_tgt;
extern struct mvs_info *tgt_mvi;
extern const struct mvs_dispatch mvs_64xx_dispatch;
extern const struct mvs_dispatch mvs_94xx_dispatch;
extern struct kmem_cache *mvs_task_list_cache;
#define DEV_IS_EXPANDER(type) \
((type == EDGE_DEV) || (type == FANOUT_DEV))
@ -341,6 +343,7 @@ struct mvs_info {
dma_addr_t bulk_buffer_dma;
#define TRASH_BUCKET_SIZE 0x20000
#endif
void *dma_pool;
struct mvs_slot_info slot_info[0];
};
@ -367,6 +370,11 @@ struct mvs_task_exec_info {
int n_elem;
};
struct mvs_task_list {
struct sas_task *task;
struct list_head list;
};
/******************** function prototype *********************/
void mvs_get_sas_addr(void *buf, u32 buflen);

View File

@ -8147,7 +8147,7 @@ static int ncr53c8xx_abort(struct scsi_cmnd *cmd)
unsigned long flags;
struct scsi_cmnd *done_list;
printk("ncr53c8xx_abort: command pid %lu\n", cmd->serial_number);
printk("ncr53c8xx_abort\n");
NCR_LOCK_NCB(np, flags);

View File

@ -4066,7 +4066,7 @@ __qla1280_print_scsi_cmd(struct scsi_cmnd *cmd)
} */
printk(" tag=%d, transfersize=0x%x \n",
cmd->tag, cmd->transfersize);
printk(" Pid=%li, SP=0x%p\n", cmd->serial_number, CMD_SP(cmd));
printk(" SP=0x%p\n", CMD_SP(cmd));
printk(" underflow size = 0x%x, direction=0x%x\n",
cmd->underflow, cmd->sc_data_direction);
}

View File

@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2010 QLogic Corporation
* Copyright (c) 2003-2011 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@ -496,8 +496,8 @@ do_read:
offset = 0;
}
rval = qla2x00_read_sfp(vha, ha->sfp_data_dma, addr, offset,
SFP_BLOCK_SIZE);
rval = qla2x00_read_sfp(vha, ha->sfp_data_dma, ha->sfp_data,
addr, offset, SFP_BLOCK_SIZE, 0);
if (rval != QLA_SUCCESS) {
qla_printk(KERN_WARNING, ha,
"Unable to read SFP data (%x/%x/%x).\n", rval,
@ -628,12 +628,12 @@ qla2x00_sysfs_write_edc(struct file *filp, struct kobject *kobj,
memcpy(ha->edc_data, &buf[8], len);
rval = qla2x00_write_edc(vha, dev, adr, ha->edc_data_dma,
ha->edc_data, len, opt);
rval = qla2x00_write_sfp(vha, ha->edc_data_dma, ha->edc_data,
dev, adr, len, opt);
if (rval != QLA_SUCCESS) {
DEBUG2(qla_printk(KERN_INFO, ha,
"Unable to write EDC (%x) %02x:%02x:%04x:%02x:%02x.\n",
rval, dev, adr, opt, len, *buf));
rval, dev, adr, opt, len, buf[8]));
return 0;
}
@ -685,8 +685,8 @@ qla2x00_sysfs_write_edc_status(struct file *filp, struct kobject *kobj,
return -EINVAL;
memset(ha->edc_data, 0, len);
rval = qla2x00_read_edc(vha, dev, adr, ha->edc_data_dma,
ha->edc_data, len, opt);
rval = qla2x00_read_sfp(vha, ha->edc_data_dma, ha->edc_data,
dev, adr, len, opt);
if (rval != QLA_SUCCESS) {
DEBUG2(qla_printk(KERN_INFO, ha,
"Unable to write EDC status (%x) %02x:%02x:%04x:%02x.\n",
@ -1568,7 +1568,7 @@ qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport)
/* Now that the rport has been deleted, set the fcport state to
FCS_DEVICE_DEAD */
atomic_set(&fcport->state, FCS_DEVICE_DEAD);
qla2x00_set_fcport_state(fcport, FCS_DEVICE_DEAD);
/*
* Transport has effectively 'deleted' the rport, clear
@ -1877,14 +1877,15 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
scsi_remove_host(vha->host);
/* Allow timer to run to drain queued items, when removing vp */
qla24xx_deallocate_vp_id(vha);
if (vha->timer_active) {
qla2x00_vp_stop_timer(vha);
DEBUG15(printk(KERN_INFO "scsi(%ld): timer for the vport[%d]"
" = %p has stopped\n", vha->host_no, vha->vp_idx, vha));
}
qla24xx_deallocate_vp_id(vha);
/* No pending activities shall be there on the vha now */
DEBUG(msleep(random32()%10)); /* Just to see if something falls on
* the net we have placed below */

View File

@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2010 QLogic Corporation
* Copyright (c) 2003-2011 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/

View File

@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2010 QLogic Corporation
* Copyright (c) 2003-2011 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/

View File

@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2010 QLogic Corporation
* Copyright (c) 2003-2011 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/

View File

@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2010 QLogic Corporation
* Copyright (c) 2003-2011 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/

View File

@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2010 QLogic Corporation
* Copyright (c) 2003-2011 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@ -1717,6 +1717,14 @@ typedef struct fc_port {
#define FCS_DEVICE_LOST 3
#define FCS_ONLINE 4
static const char * const port_state_str[] = {
"Unknown",
"UNCONFIGURED",
"DEAD",
"LOST",
"ONLINE"
};
/*
* FC port flags.
*/

View File

@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2010 QLogic Corporation
* Copyright (c) 2003-2011 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/

View File

@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2010 QLogic Corporation
* Copyright (c) 2003-2011 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@ -416,8 +416,7 @@ struct cmd_type_6 {
uint8_t vp_index;
uint32_t fcp_data_dseg_address[2]; /* Data segment address. */
uint16_t fcp_data_dseg_len; /* Data segment length. */
uint16_t reserved_1; /* MUST be set to 0. */
uint32_t fcp_data_dseg_len; /* Data segment length. */
};
#define COMMAND_TYPE_7 0x18 /* Command Type 7 entry */

View File

@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2010 QLogic Corporation
* Copyright (c) 2003-2011 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@ -39,6 +39,8 @@ extern int qla81xx_load_risc(scsi_qla_host_t *, uint32_t *);
extern int qla2x00_perform_loop_resync(scsi_qla_host_t *);
extern int qla2x00_loop_resync(scsi_qla_host_t *);
extern int qla2x00_find_new_loop_id(scsi_qla_host_t *, fc_port_t *);
extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *);
extern int qla2x00_local_device_login(scsi_qla_host_t *, fc_port_t *);
@ -100,6 +102,8 @@ extern int ql2xgffidenable;
extern int ql2xenabledif;
extern int ql2xenablehba_err_chk;
extern int ql2xtargetreset;
extern int ql2xdontresethba;
extern unsigned int ql2xmaxlun;
extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
@ -319,15 +323,12 @@ extern int
qla2x00_disable_fce_trace(scsi_qla_host_t *, uint64_t *, uint64_t *);
extern int
qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t, uint16_t);
qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint8_t *,
uint16_t, uint16_t, uint16_t, uint16_t);
extern int
qla2x00_read_edc(scsi_qla_host_t *, uint16_t, uint16_t, dma_addr_t,
uint8_t *, uint16_t, uint16_t);
extern int
qla2x00_write_edc(scsi_qla_host_t *, uint16_t, uint16_t, dma_addr_t,
uint8_t *, uint16_t, uint16_t);
qla2x00_write_sfp(scsi_qla_host_t *, dma_addr_t, uint8_t *,
uint16_t, uint16_t, uint16_t, uint16_t);
extern int
qla2x00_set_idma_speed(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t *);
@ -549,7 +550,6 @@ extern int qla82xx_wr_32(struct qla_hw_data *, ulong, u32);
extern int qla82xx_rd_32(struct qla_hw_data *, ulong);
extern int qla82xx_rdmem(struct qla_hw_data *, u64, void *, int);
extern int qla82xx_wrmem(struct qla_hw_data *, u64, void *, int);
extern void qla82xx_rom_unlock(struct qla_hw_data *);
/* ISP 8021 IDC */
extern void qla82xx_clear_drv_active(struct qla_hw_data *);

View File

@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2010 QLogic Corporation
* Copyright (c) 2003-2011 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/

View File

@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2010 QLogic Corporation
* Copyright (c) 2003-2011 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@ -35,8 +35,6 @@ static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *,
static int qla2x00_restart_isp(scsi_qla_host_t *);
static int qla2x00_find_new_loop_id(scsi_qla_host_t *, fc_port_t *);
static struct qla_chip_state_84xx *qla84xx_get_chip(struct scsi_qla_host *);
static int qla84xx_init_chip(scsi_qla_host_t *);
static int qla25xx_init_queues(struct qla_hw_data *);
@ -385,8 +383,18 @@ qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport,
switch (data[0]) {
case MBS_COMMAND_COMPLETE:
/*
* Driver must validate login state - If PRLI not complete,
* force a relogin attempt via implicit LOGO, PLOGI, and PRLI
* requests.
*/
rval = qla2x00_get_port_database(vha, fcport, 0);
if (rval != QLA_SUCCESS) {
qla2x00_post_async_logout_work(vha, fcport, NULL);
qla2x00_post_async_login_work(vha, fcport, NULL);
break;
}
if (fcport->flags & FCF_FCP2_DEVICE) {
fcport->flags |= FCF_ASYNC_SENT;
qla2x00_post_async_adisc_work(vha, fcport, data);
break;
}
@ -397,7 +405,7 @@ qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport,
if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
else
qla2x00_mark_device_lost(vha, fcport, 1, 1);
qla2x00_mark_device_lost(vha, fcport, 1, 0);
break;
case MBS_PORT_ID_USED:
fcport->loop_id = data[1];
@ -409,7 +417,7 @@ qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport,
rval = qla2x00_find_new_loop_id(vha, fcport);
if (rval != QLA_SUCCESS) {
fcport->flags &= ~FCF_ASYNC_SENT;
qla2x00_mark_device_lost(vha, fcport, 1, 1);
qla2x00_mark_device_lost(vha, fcport, 1, 0);
break;
}
qla2x00_post_async_login_work(vha, fcport, NULL);
@ -441,7 +449,7 @@ qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport,
if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
else
qla2x00_mark_device_lost(vha, fcport, 1, 1);
qla2x00_mark_device_lost(vha, fcport, 1, 0);
return;
}
@ -2536,7 +2544,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
fcport->vp_idx = vha->vp_idx;
fcport->port_type = FCT_UNKNOWN;
fcport->loop_id = FC_NO_LOOP_ID;
atomic_set(&fcport->state, FCS_UNCONFIGURED);
qla2x00_set_fcport_state(fcport, FCS_UNCONFIGURED);
fcport->supported_classes = FC_COS_UNSPECIFIED;
return fcport;
@ -2722,7 +2730,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
"loop_id=0x%04x\n",
vha->host_no, fcport->loop_id));
atomic_set(&fcport->state, FCS_DEVICE_LOST);
qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
}
}
@ -2934,7 +2942,7 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
qla2x00_iidma_fcport(vha, fcport);
qla24xx_update_fcport_fcp_prio(vha, fcport);
qla2x00_reg_remote_port(vha, fcport);
atomic_set(&fcport->state, FCS_ONLINE);
qla2x00_set_fcport_state(fcport, FCS_ONLINE);
}
/*
@ -3391,7 +3399,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
* Context:
* Kernel context.
*/
static int
int
qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
{
int rval;
@ -5202,7 +5210,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
}
/* Reset Initialization control block */
memset(icb, 0, sizeof(struct init_cb_81xx));
memset(icb, 0, ha->init_cb_size);
/* Copy 1st segment. */
dptr1 = (uint8_t *)icb;
@ -5427,6 +5435,13 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
ha->isp_abort_cnt = 0;
clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
/* Update the firmware version */
qla2x00_get_fw_version(vha, &ha->fw_major_version,
&ha->fw_minor_version, &ha->fw_subminor_version,
&ha->fw_attributes, &ha->fw_memory_size,
ha->mpi_version, &ha->mpi_capabilities,
ha->phy_version);
if (ha->fce) {
ha->flags.fce_enabled = 1;
memset(ha->fce, 0,
@ -5508,26 +5523,26 @@ qla81xx_update_fw_options(scsi_qla_host_t *vha)
*
* Return:
* non-zero (if found)
* 0 (if not found)
* -1 (if not found)
*
* Context:
* Kernel context
*/
uint8_t
static int
qla24xx_get_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport)
{
int i, entries;
uint8_t pid_match, wwn_match;
uint8_t priority;
int priority;
uint32_t pid1, pid2;
uint64_t wwn1, wwn2;
struct qla_fcp_prio_entry *pri_entry;
struct qla_hw_data *ha = vha->hw;
if (!ha->fcp_prio_cfg || !ha->flags.fcp_prio_enabled)
return 0;
return -1;
priority = 0;
priority = -1;
entries = ha->fcp_prio_cfg->num_entries;
pri_entry = &ha->fcp_prio_cfg->entry[0];
@ -5610,7 +5625,7 @@ int
qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport)
{
int ret;
uint8_t priority;
int priority;
uint16_t mb[5];
if (fcport->port_type != FCT_TARGET ||
@ -5618,6 +5633,9 @@ qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport)
return QLA_FUNCTION_FAILED;
priority = qla24xx_get_fcp_prio(vha, fcport);
if (priority < 0)
return QLA_FUNCTION_FAILED;
ret = qla24xx_set_fcp_prio(vha, fcport->loop_id, priority, mb);
if (ret == QLA_SUCCESS)
fcport->fcp_prio = priority;

View File

@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2010 QLogic Corporation
* Copyright (c) 2003-2011 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@ -83,3 +83,22 @@ qla2x00_clean_dsd_pool(struct qla_hw_data *ha, srb_t *sp)
}
INIT_LIST_HEAD(&((struct crc_context *)sp->ctx)->dsd_list);
}
static inline void
qla2x00_set_fcport_state(fc_port_t *fcport, int state)
{
int old_state;
old_state = atomic_read(&fcport->state);
atomic_set(&fcport->state, state);
/* Don't print state transitions during initial allocation of fcport */
if (old_state && old_state != state) {
DEBUG(qla_printk(KERN_WARNING, fcport->vha->hw,
"scsi(%ld): FCPort state transitioned from %s to %s - "
"portid=%02x%02x%02x.\n", fcport->vha->host_no,
port_state_str[old_state], port_state_str[state],
fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa));
}
}

View File

@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2010 QLogic Corporation
* Copyright (c) 2003-2011 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/

View File

@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2010 QLogic Corporation
* Copyright (c) 2003-2011 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@ -843,7 +843,10 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha,
qla_printk(KERN_WARNING, ha,
"Invalid SCSI completion handle %d.\n", index);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
if (IS_QLA82XX(ha))
set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
else
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
return;
}
@ -861,7 +864,10 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha,
qla_printk(KERN_WARNING, ha,
"Invalid ISP SCSI completion handle\n");
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
if (IS_QLA82XX(ha))
set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
else
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
}
}
@ -878,7 +884,10 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
if (index >= MAX_OUTSTANDING_COMMANDS) {
qla_printk(KERN_WARNING, ha,
"%s: Invalid completion handle (%x).\n", func, index);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
if (IS_QLA82XX(ha))
set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
else
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
goto done;
}
sp = req->outstanding_cmds[index];
@ -1564,7 +1573,10 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
"scsi(%ld): Invalid status handle (0x%x).\n", vha->host_no,
sts->handle);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
if (IS_QLA82XX(ha))
set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
else
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
return;
}
@ -1794,12 +1806,13 @@ out:
if (logit)
DEBUG2(qla_printk(KERN_INFO, ha,
"scsi(%ld:%d:%d) FCP command status: 0x%x-0x%x (0x%x) "
"oxid=0x%x cdb=%02x%02x%02x len=0x%x "
"portid=%02x%02x%02x oxid=0x%x cdb=%02x%02x%02x len=0x%x "
"rsp_info=0x%x resid=0x%x fw_resid=0x%x\n", vha->host_no,
cp->device->id, cp->device->lun, comp_status, scsi_status,
cp->result, ox_id, cp->cmnd[0],
cp->cmnd[1], cp->cmnd[2], scsi_bufflen(cp), rsp_info_len,
resid_len, fw_resid_len));
cp->result, fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa, ox_id, cp->cmnd[0], cp->cmnd[1],
cp->cmnd[2], scsi_bufflen(cp), rsp_info_len, resid_len,
fw_resid_len));
if (rsp->status_srb == NULL)
qla2x00_sp_compl(ha, sp);
@ -1908,13 +1921,17 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
qla2x00_sp_compl(ha, sp);
} else if (pkt->entry_type == COMMAND_A64_TYPE || pkt->entry_type ==
COMMAND_TYPE || pkt->entry_type == COMMAND_TYPE_7) {
COMMAND_TYPE || pkt->entry_type == COMMAND_TYPE_7
|| pkt->entry_type == COMMAND_TYPE_6) {
DEBUG2(printk("scsi(%ld): Error entry - invalid handle\n",
vha->host_no));
vha->host_no));
qla_printk(KERN_WARNING, ha,
"Error entry - invalid handle\n");
"Error entry - invalid handle\n");
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
if (IS_QLA82XX(ha))
set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
else
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
}
}

View File

@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2010 QLogic Corporation
* Copyright (c) 2003-2011 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@ -1261,11 +1261,12 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
/* Check for logged in state. */
if (pd24->current_login_state != PDS_PRLI_COMPLETE &&
pd24->last_login_state != PDS_PRLI_COMPLETE) {
DEBUG2(printk("%s(%ld): Unable to verify "
"login-state (%x/%x) for loop_id %x\n",
__func__, vha->host_no,
pd24->current_login_state,
pd24->last_login_state, fcport->loop_id));
DEBUG2(qla_printk(KERN_WARNING, ha,
"scsi(%ld): Unable to verify login-state (%x/%x) "
" - portid=%02x%02x%02x.\n", vha->host_no,
pd24->current_login_state, pd24->last_login_state,
fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa));
rval = QLA_FUNCTION_FAILED;
goto gpd_error_out;
}
@ -1289,6 +1290,12 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
/* Check for logged in state. */
if (pd->master_state != PD_STATE_PORT_LOGGED_IN &&
pd->slave_state != PD_STATE_PORT_LOGGED_IN) {
DEBUG2(qla_printk(KERN_WARNING, ha,
"scsi(%ld): Unable to verify login-state (%x/%x) "
" - portid=%02x%02x%02x.\n", vha->host_no,
pd->master_state, pd->slave_state,
fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa));
rval = QLA_FUNCTION_FAILED;
goto gpd_error_out;
}
@ -1883,7 +1890,8 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
lg->handle = MAKE_HANDLE(req->id, lg->handle);
lg->nport_handle = cpu_to_le16(loop_id);
lg->control_flags =
__constant_cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO);
__constant_cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO|
LCF_FREE_NPORT);
lg->port_id[0] = al_pa;
lg->port_id[1] = area;
lg->port_id[2] = domain;
@ -2362,7 +2370,7 @@ qla24xx_abort_command(srb_t *sp)
abt->entry_count = 1;
abt->handle = MAKE_HANDLE(req->id, abt->handle);
abt->nport_handle = cpu_to_le16(fcport->loop_id);
abt->handle_to_abort = handle;
abt->handle_to_abort = MAKE_HANDLE(req->id, handle);
abt->port_id[0] = fcport->d_id.b.al_pa;
abt->port_id[1] = fcport->d_id.b.area;
abt->port_id[2] = fcport->d_id.b.domain;
@ -2778,44 +2786,6 @@ qla2x00_disable_fce_trace(scsi_qla_host_t *vha, uint64_t *wr, uint64_t *rd)
return rval;
}
int
qla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint16_t addr,
uint16_t off, uint16_t count)
{
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
if (!IS_FWI2_CAPABLE(vha->hw))
return QLA_FUNCTION_FAILED;
DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
mcp->mb[0] = MBC_READ_SFP;
mcp->mb[1] = addr;
mcp->mb[2] = MSW(sfp_dma);
mcp->mb[3] = LSW(sfp_dma);
mcp->mb[6] = MSW(MSD(sfp_dma));
mcp->mb[7] = LSW(MSD(sfp_dma));
mcp->mb[8] = count;
mcp->mb[9] = off;
mcp->mb[10] = 0;
mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_0;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
vha->host_no, rval, mcp->mb[0]));
} else {
DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
}
return rval;
}
int
qla2x00_get_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id,
uint16_t *port_speed, uint16_t *mb)
@ -3581,15 +3551,22 @@ qla81xx_restart_mpi_firmware(scsi_qla_host_t *vha)
}
int
qla2x00_read_edc(scsi_qla_host_t *vha, uint16_t dev, uint16_t adr,
dma_addr_t sfp_dma, uint8_t *sfp, uint16_t len, uint16_t opt)
qla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp,
uint16_t dev, uint16_t off, uint16_t len, uint16_t opt)
{
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
struct qla_hw_data *ha = vha->hw;
if (!IS_FWI2_CAPABLE(ha))
return QLA_FUNCTION_FAILED;
DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
if (len == 1)
opt |= BIT_0;
mcp->mb[0] = MBC_READ_SFP;
mcp->mb[1] = dev;
mcp->mb[2] = MSW(sfp_dma);
@ -3597,17 +3574,16 @@ qla2x00_read_edc(scsi_qla_host_t *vha, uint16_t dev, uint16_t adr,
mcp->mb[6] = MSW(MSD(sfp_dma));
mcp->mb[7] = LSW(MSD(sfp_dma));
mcp->mb[8] = len;
mcp->mb[9] = adr;
mcp->mb[9] = off;
mcp->mb[10] = opt;
mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_0;
mcp->in_mb = MBX_1|MBX_0;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (opt & BIT_0)
if (sfp)
*sfp = mcp->mb[8];
*sfp = mcp->mb[1];
if (rval != QLA_SUCCESS) {
DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
@ -3620,18 +3596,24 @@ qla2x00_read_edc(scsi_qla_host_t *vha, uint16_t dev, uint16_t adr,
}
int
qla2x00_write_edc(scsi_qla_host_t *vha, uint16_t dev, uint16_t adr,
dma_addr_t sfp_dma, uint8_t *sfp, uint16_t len, uint16_t opt)
qla2x00_write_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp,
uint16_t dev, uint16_t off, uint16_t len, uint16_t opt)
{
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
struct qla_hw_data *ha = vha->hw;
if (!IS_FWI2_CAPABLE(ha))
return QLA_FUNCTION_FAILED;
DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
if (len == 1)
opt |= BIT_0;
if (opt & BIT_0)
if (sfp)
len = *sfp;
len = *sfp;
mcp->mb[0] = MBC_WRITE_SFP;
mcp->mb[1] = dev;
@ -3640,10 +3622,10 @@ qla2x00_write_edc(scsi_qla_host_t *vha, uint16_t dev, uint16_t adr,
mcp->mb[6] = MSW(MSD(sfp_dma));
mcp->mb[7] = LSW(MSD(sfp_dma));
mcp->mb[8] = len;
mcp->mb[9] = adr;
mcp->mb[9] = off;
mcp->mb[10] = opt;
mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_0;
mcp->in_mb = MBX_1|MBX_0;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
@ -4160,63 +4142,32 @@ int
qla2x00_get_thermal_temp(scsi_qla_host_t *vha, uint16_t *temp, uint16_t *frac)
{
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
uint8_t byte;
struct qla_hw_data *ha = vha->hw;
DEBUG11(printk(KERN_INFO "%s(%ld): entered.\n", __func__, ha->host_no));
DEBUG11(printk(KERN_INFO "%s(%ld): entered.\n", __func__, vha->host_no));
/* High bits. */
mcp->mb[0] = MBC_READ_SFP;
mcp->mb[1] = 0x98;
mcp->mb[2] = 0;
mcp->mb[3] = 0;
mcp->mb[6] = 0;
mcp->mb[7] = 0;
mcp->mb[8] = 1;
mcp->mb[9] = 0x01;
mcp->mb[10] = BIT_13|BIT_0;
mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_1|MBX_0;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
/* Integer part */
rval = qla2x00_read_sfp(vha, 0, &byte, 0x98, 0x01, 1, BIT_13|BIT_0);
if (rval != QLA_SUCCESS) {
DEBUG2_3_11(printk(KERN_WARNING
"%s(%ld): failed=%x (%x).\n", __func__,
vha->host_no, rval, mcp->mb[0]));
"%s(%ld): failed=%x.\n", __func__, vha->host_no, rval));
ha->flags.thermal_supported = 0;
goto fail;
}
*temp = mcp->mb[1] & 0xFF;
*temp = byte;
/* Low bits. */
mcp->mb[0] = MBC_READ_SFP;
mcp->mb[1] = 0x98;
mcp->mb[2] = 0;
mcp->mb[3] = 0;
mcp->mb[6] = 0;
mcp->mb[7] = 0;
mcp->mb[8] = 1;
mcp->mb[9] = 0x10;
mcp->mb[10] = BIT_13|BIT_0;
mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_1|MBX_0;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
/* Fraction part */
rval = qla2x00_read_sfp(vha, 0, &byte, 0x98, 0x10, 1, BIT_13|BIT_0);
if (rval != QLA_SUCCESS) {
DEBUG2_3_11(printk(KERN_WARNING
"%s(%ld): failed=%x (%x).\n", __func__,
vha->host_no, rval, mcp->mb[0]));
"%s(%ld): failed=%x.\n", __func__, vha->host_no, rval));
ha->flags.thermal_supported = 0;
goto fail;
}
*frac = ((mcp->mb[1] & 0xFF) >> 6) * 25;
*frac = (byte >> 6) * 25;
if (rval == QLA_SUCCESS)
DEBUG11(printk(KERN_INFO
"%s(%ld): done.\n", __func__, ha->host_no));
DEBUG11(printk(KERN_INFO "%s(%ld): done.\n", __func__, vha->host_no));
fail:
return rval;
}

View File

@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2010 QLogic Corporation
* Copyright (c) 2003-2011 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@ -136,7 +136,7 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha)
vha->host_no, fcport->loop_id, fcport->vp_idx));
qla2x00_mark_device_lost(vha, fcport, 0, 0);
atomic_set(&fcport->state, FCS_UNCONFIGURED);
qla2x00_set_fcport_state(fcport, FCS_UNCONFIGURED);
}
}
@ -456,7 +456,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
else
host->max_cmd_len = MAX_CMDSZ;
host->max_channel = MAX_BUSES - 1;
host->max_lun = MAX_LUNS;
host->max_lun = ql2xmaxlun;
host->unique_id = host->host_no;
host->max_id = MAX_TARGETS_2200;
host->transportt = qla2xxx_transport_vport_template;

View File

@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2010 QLogic Corporation
* Copyright (c) 2003-2011 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@ -844,6 +844,12 @@ qla82xx_rom_lock(struct qla_hw_data *ha)
return 0;
}
static void
qla82xx_rom_unlock(struct qla_hw_data *ha)
{
qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK));
}
static int
qla82xx_wait_rom_busy(struct qla_hw_data *ha)
{
@ -924,7 +930,7 @@ qla82xx_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp)
return -1;
}
ret = qla82xx_do_rom_fast_read(ha, addr, valp);
qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK));
qla82xx_rom_unlock(ha);
return ret;
}
@ -1056,7 +1062,7 @@ qla82xx_write_flash_dword(struct qla_hw_data *ha, uint32_t flashaddr,
ret = qla82xx_flash_wait_write_finish(ha);
done_write:
qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK));
qla82xx_rom_unlock(ha);
return ret;
}
@ -1081,12 +1087,26 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha)
/* Halt all the indiviual PEGs and other blocks of the ISP */
qla82xx_rom_lock(ha);
/* mask all niu interrupts */
/* disable all I2Q */
qla82xx_wr_32(ha, QLA82XX_CRB_I2Q + 0x10, 0x0);
qla82xx_wr_32(ha, QLA82XX_CRB_I2Q + 0x14, 0x0);
qla82xx_wr_32(ha, QLA82XX_CRB_I2Q + 0x18, 0x0);
qla82xx_wr_32(ha, QLA82XX_CRB_I2Q + 0x1c, 0x0);
qla82xx_wr_32(ha, QLA82XX_CRB_I2Q + 0x20, 0x0);
qla82xx_wr_32(ha, QLA82XX_CRB_I2Q + 0x24, 0x0);
/* disable all niu interrupts */
qla82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x40, 0xff);
/* disable xge rx/tx */
qla82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x70000, 0x00);
/* disable xg1 rx/tx */
qla82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x80000, 0x00);
/* disable sideband mac */
qla82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x90000, 0x00);
/* disable ap0 mac */
qla82xx_wr_32(ha, QLA82XX_CRB_NIU + 0xa0000, 0x00);
/* disable ap1 mac */
qla82xx_wr_32(ha, QLA82XX_CRB_NIU + 0xb0000, 0x00);
/* halt sre */
val = qla82xx_rd_32(ha, QLA82XX_CRB_SRE + 0x1000);
@ -1101,6 +1121,7 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha)
qla82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x10, 0x0);
qla82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x18, 0x0);
qla82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x100, 0x0);
qla82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x200, 0x0);
/* halt pegs */
qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x3c, 1);
@ -1108,9 +1129,9 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha)
qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_2 + 0x3c, 1);
qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_3 + 0x3c, 1);
qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_4 + 0x3c, 1);
msleep(20);
/* big hammer */
msleep(1000);
if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags))
/* don't reset CAM block on reset */
qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xfeffffff);
@ -1129,7 +1150,7 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha)
qla82xx_wr_32(ha, QLA82XX_CRB_QDR_NET + 0xe4, val);
msleep(20);
qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK));
qla82xx_rom_unlock(ha);
/* Read the signature value from the flash.
* Offset 0: Contain signature (0xcafecafe)
@ -2395,9 +2416,13 @@ qla82xx_load_fw(scsi_qla_host_t *vha)
if (qla82xx_fw_load_from_flash(ha) == QLA_SUCCESS) {
qla_printk(KERN_ERR, ha,
"Firmware loaded successfully from flash\n");
"Firmware loaded successfully from flash\n");
return QLA_SUCCESS;
} else {
qla_printk(KERN_ERR, ha,
"Firmware load from flash failed\n");
}
try_blob_fw:
qla_printk(KERN_INFO, ha,
"Attempting to load firmware from blob\n");
@ -2548,11 +2573,11 @@ qla2xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt,
dsd_seg = (uint32_t *)&cmd_pkt->fcp_data_dseg_address;
*dsd_seg++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
*dsd_seg++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
cmd_pkt->fcp_data_dseg_len = dsd_list_len;
*dsd_seg++ = cpu_to_le32(dsd_list_len);
} else {
*cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
*cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
*cur_dsd++ = dsd_list_len;
*cur_dsd++ = cpu_to_le32(dsd_list_len);
}
cur_dsd = (uint32_t *)next_dsd;
while (avail_dsds) {
@ -2991,7 +3016,7 @@ qla82xx_unprotect_flash(struct qla_hw_data *ha)
qla_printk(KERN_WARNING, ha, "Write disable failed\n");
done_unprotect:
qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK));
qla82xx_rom_unlock(ha);
return ret;
}
@ -3020,7 +3045,7 @@ qla82xx_protect_flash(struct qla_hw_data *ha)
if (qla82xx_write_disable_flash(ha) != 0)
qla_printk(KERN_WARNING, ha, "Write disable failed\n");
done_protect:
qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK));
qla82xx_rom_unlock(ha);
return ret;
}
@ -3048,7 +3073,7 @@ qla82xx_erase_sector(struct qla_hw_data *ha, int addr)
}
ret = qla82xx_flash_wait_write_finish(ha);
done:
qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK));
qla82xx_rom_unlock(ha);
return ret;
}
@ -3228,7 +3253,7 @@ void qla82xx_rom_lock_recovery(struct qla_hw_data *ha)
* else died while holding it.
* In either case, unlock.
*/
qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK));
qla82xx_rom_unlock(ha);
}
/*
@ -3528,15 +3553,18 @@ int
qla82xx_device_state_handler(scsi_qla_host_t *vha)
{
uint32_t dev_state;
uint32_t old_dev_state;
int rval = QLA_SUCCESS;
unsigned long dev_init_timeout;
struct qla_hw_data *ha = vha->hw;
int loopcount = 0;
qla82xx_idc_lock(ha);
if (!vha->flags.init_done)
qla82xx_set_drv_active(vha);
dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
old_dev_state = dev_state;
qla_printk(KERN_INFO, ha, "1:Device state is 0x%x = %s\n", dev_state,
dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown");
@ -3553,10 +3581,16 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
break;
}
dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
qla_printk(KERN_INFO, ha,
"2:Device state is 0x%x = %s\n", dev_state,
dev_state < MAX_STATES ?
qdev_state[dev_state] : "Unknown");
if (old_dev_state != dev_state) {
loopcount = 0;
old_dev_state = dev_state;
}
if (loopcount < 5) {
qla_printk(KERN_INFO, ha,
"2:Device state is 0x%x = %s\n", dev_state,
dev_state < MAX_STATES ?
qdev_state[dev_state] : "Unknown");
}
switch (dev_state) {
case QLA82XX_DEV_READY:
@ -3570,6 +3604,7 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
qla82xx_idc_lock(ha);
break;
case QLA82XX_DEV_NEED_RESET:
if (!ql2xdontresethba)
qla82xx_need_reset_handler(vha);
dev_init_timeout = jiffies +
(ha->nx_dev_init_timeout * HZ);
@ -3604,6 +3639,7 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
msleep(1000);
qla82xx_idc_lock(ha);
}
loopcount++;
}
exit:
qla82xx_idc_unlock(ha);
@ -3621,7 +3657,8 @@ void qla82xx_watchdog(scsi_qla_host_t *vha)
if (dev_state == QLA82XX_DEV_NEED_RESET &&
!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) {
qla_printk(KERN_WARNING, ha,
"%s(): Adapter reset needed!\n", __func__);
"scsi(%ld) %s: Adapter reset needed!\n",
vha->host_no, __func__);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
} else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT &&
@ -3632,10 +3669,27 @@ void qla82xx_watchdog(scsi_qla_host_t *vha)
set_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
} else {
qla82xx_check_fw_alive(vha);
if (qla82xx_check_fw_alive(vha)) {
halt_status = qla82xx_rd_32(ha,
QLA82XX_PEG_HALT_STATUS1);
qla_printk(KERN_INFO, ha,
"scsi(%ld): %s, Dumping hw/fw registers:\n "
" PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,\n "
" PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,\n "
" PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,\n "
" PEG_NET_4_PC: 0x%x\n",
vha->host_no, __func__, halt_status,
qla82xx_rd_32(ha, QLA82XX_PEG_HALT_STATUS2),
qla82xx_rd_32(ha,
QLA82XX_CRB_PEG_NET_0 + 0x3c),
qla82xx_rd_32(ha,
QLA82XX_CRB_PEG_NET_1 + 0x3c),
qla82xx_rd_32(ha,
QLA82XX_CRB_PEG_NET_2 + 0x3c),
qla82xx_rd_32(ha,
QLA82XX_CRB_PEG_NET_3 + 0x3c),
qla82xx_rd_32(ha,
QLA82XX_CRB_PEG_NET_4 + 0x3c));
if (halt_status & HALT_STATUS_UNRECOVERABLE) {
set_bit(ISP_UNRECOVERABLE,
&vha->dpc_flags);
@ -3651,8 +3705,9 @@ void qla82xx_watchdog(scsi_qla_host_t *vha)
if (ha->flags.mbox_busy) {
ha->flags.mbox_int = 1;
DEBUG2(qla_printk(KERN_ERR, ha,
"Due to fw hung, doing premature "
"completion of mbx command\n"));
"scsi(%ld) Due to fw hung, doing "
"premature completion of mbx "
"command\n", vha->host_no));
if (test_bit(MBX_INTR_WAIT,
&ha->mbx_cmd_flags))
complete(&ha->mbx_intr_comp);

View File

@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2010 QLogic Corporation
* Copyright (c) 2003-2011 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/

View File

@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2010 QLogic Corporation
* Copyright (c) 2003-2011 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/
@ -164,6 +164,20 @@ module_param(ql2xasynctmfenable, int, S_IRUGO);
MODULE_PARM_DESC(ql2xasynctmfenable,
"Enables issue of TM IOCBs asynchronously via IOCB mechanism"
"Default is 0 - Issue TM IOCBs via mailbox mechanism.");
int ql2xdontresethba;
module_param(ql2xdontresethba, int, S_IRUGO);
MODULE_PARM_DESC(ql2xdontresethba,
"Option to specify reset behaviour\n"
" 0 (Default) -- Reset on failure.\n"
" 1 -- Do not reset on failure.\n");
uint ql2xmaxlun = MAX_LUNS;
module_param(ql2xmaxlun, uint, S_IRUGO);
MODULE_PARM_DESC(ql2xmaxlun,
"Defines the maximum LU number to register with the SCSI "
"midlayer. Default is 65535.");
/*
* SCSI host template entry points
*/
@ -528,7 +542,7 @@ qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport,
static int
qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
{
scsi_qla_host_t *vha = shost_priv(cmd->device->host);
scsi_qla_host_t *vha = shost_priv(host);
fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device));
struct qla_hw_data *ha = vha->hw;
@ -2128,7 +2142,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
else
host->max_cmd_len = MAX_CMDSZ;
host->max_channel = MAX_BUSES - 1;
host->max_lun = MAX_LUNS;
host->max_lun = ql2xmaxlun;
host->transportt = qla2xxx_transport_template;
sht->vendor_id = (SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC);
@ -2360,21 +2374,26 @@ qla2x00_remove_one(struct pci_dev *pdev)
base_vha = pci_get_drvdata(pdev);
ha = base_vha->hw;
spin_lock_irqsave(&ha->vport_slock, flags);
list_for_each_entry(vha, &ha->vp_list, list) {
atomic_inc(&vha->vref_count);
mutex_lock(&ha->vport_lock);
while (ha->cur_vport_count) {
struct Scsi_Host *scsi_host;
if (vha->fc_vport) {
spin_unlock_irqrestore(&ha->vport_slock, flags);
spin_lock_irqsave(&ha->vport_slock, flags);
fc_vport_terminate(vha->fc_vport);
BUG_ON(base_vha->list.next == &ha->vp_list);
/* This assumes first entry in ha->vp_list is always base vha */
vha = list_first_entry(&base_vha->list, scsi_qla_host_t, list);
scsi_host = scsi_host_get(vha->host);
spin_lock_irqsave(&ha->vport_slock, flags);
}
spin_unlock_irqrestore(&ha->vport_slock, flags);
mutex_unlock(&ha->vport_lock);
atomic_dec(&vha->vref_count);
fc_vport_terminate(vha->fc_vport);
scsi_host_put(vha->host);
mutex_lock(&ha->vport_lock);
}
spin_unlock_irqrestore(&ha->vport_slock, flags);
mutex_unlock(&ha->vport_lock);
set_bit(UNLOADING, &base_vha->dpc_flags);
@ -2544,7 +2563,7 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
{
if (atomic_read(&fcport->state) == FCS_ONLINE &&
vha->vp_idx == fcport->vp_idx) {
atomic_set(&fcport->state, FCS_DEVICE_LOST);
qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
qla2x00_schedule_rport_del(vha, fcport, defer);
}
/*
@ -2552,7 +2571,7 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
* port but do the retries.
*/
if (atomic_read(&fcport->state) != FCS_DEVICE_DEAD)
atomic_set(&fcport->state, FCS_DEVICE_LOST);
qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
if (!do_login)
return;
@ -2607,7 +2626,7 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha, int defer)
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD)
continue;
if (atomic_read(&fcport->state) == FCS_ONLINE) {
atomic_set(&fcport->state, FCS_DEVICE_LOST);
qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
if (defer)
qla2x00_schedule_rport_del(vha, fcport, defer);
else if (vha->vp_idx == fcport->vp_idx)
@ -3214,6 +3233,17 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
fcport->d_id.b.area,
fcport->d_id.b.al_pa);
if (fcport->loop_id == FC_NO_LOOP_ID) {
fcport->loop_id = next_loopid =
ha->min_external_loopid;
status = qla2x00_find_new_loop_id(
vha, fcport);
if (status != QLA_SUCCESS) {
/* Ran out of IDs to use */
break;
}
}
if (IS_ALOGIO_CAPABLE(ha)) {
fcport->flags |= FCF_ASYNC_SENT;
data[0] = 0;
@ -3604,7 +3634,8 @@ qla2x00_timer(scsi_qla_host_t *vha)
if (!pci_channel_offline(ha->pdev))
pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
if (IS_QLA82XX(ha)) {
/* Make sure qla82xx_watchdog is run only for physical port */
if (!vha->vp_idx && IS_QLA82XX(ha)) {
if (test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags))
start_dpc++;
qla82xx_watchdog(vha);
@ -3612,7 +3643,8 @@ qla2x00_timer(scsi_qla_host_t *vha)
/* Loop down handler. */
if (atomic_read(&vha->loop_down_timer) > 0 &&
!(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags))
!(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) &&
!(test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags))
&& vha->flags.online) {
if (atomic_read(&vha->loop_down_timer) ==
@ -3648,7 +3680,11 @@ qla2x00_timer(scsi_qla_host_t *vha)
if (!(sfcp->flags & FCF_FCP2_DEVICE))
continue;
set_bit(ISP_ABORT_NEEDED,
if (IS_QLA82XX(ha))
set_bit(FCOE_CTX_RESET_NEEDED,
&vha->dpc_flags);
else
set_bit(ISP_ABORT_NEEDED,
&vha->dpc_flags);
break;
}
@ -3667,7 +3703,12 @@ qla2x00_timer(scsi_qla_host_t *vha)
qla_printk(KERN_WARNING, ha,
"Loop down - aborting ISP.\n");
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
if (IS_QLA82XX(ha))
set_bit(FCOE_CTX_RESET_NEEDED,
&vha->dpc_flags);
else
set_bit(ISP_ABORT_NEEDED,
&vha->dpc_flags);
}
}
DEBUG3(printk("scsi(%ld): Loop Down - seconds remaining %d\n",
@ -3675,8 +3716,8 @@ qla2x00_timer(scsi_qla_host_t *vha)
atomic_read(&vha->loop_down_timer)));
}
/* Check if beacon LED needs to be blinked */
if (ha->beacon_blink_led == 1) {
/* Check if beacon LED needs to be blinked for physical host only */
if (!vha->vp_idx && (ha->beacon_blink_led == 1)) {
set_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags);
start_dpc++;
}

View File

@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2010 QLogic Corporation
* Copyright (c) 2003-2011 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/

View File

@ -1,6 +1,6 @@
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2010 QLogic Corporation
* Copyright (c) 2003-2011 QLogic Corporation
*
* See LICENSE.qla2xxx for copyright and licensing details.
*/

Some files were not shown because too many files have changed in this diff Show More