You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull final round of SCSI updates from James Bottomley: "Sorry for the delay in this patch which was mostly caused by getting the merger of the mpt2/mpt3sas driver, which was seen as an essential item of maintenance work to do before the drivers diverge too much. Unfortunately, this caused a compile failure (detected by linux-next), which then had to be fixed up and incubated. In addition to the mpt2/3sas rework, there are updates from pm80xx, lpfc, bnx2fc, hpsa, ipr, aacraid, megaraid_sas, storvsc and ufs plus an assortment of changes including some year 2038 issues, a fix for a remove before detach issue in some drivers and a couple of other minor issues" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (141 commits) mpt3sas: fix inline markers on non inline function declarations sd: Clear PS bit before Mode Select. ibmvscsi: set max_lun to 32 ibmvscsi: display default value for max_id, max_lun and max_channel. mptfusion: don't allow negative bytes in kbuf_alloc_2_sgl() scsi: pmcraid: replace struct timeval with ktime_get_real_seconds() mvumi: 64bit value for seconds_since1970 be2iscsi: Fix bogus WARN_ON length check scsi_scan: don't dump trace when scsi_prep_async_scan() is called twice mpt3sas: Bump mpt3sas driver version to 09.102.00.00 mpt3sas: Single driver module which supports both SAS 2.0 & SAS 3.0 HBAs mpt2sas, mpt3sas: Update the driver versions mpt3sas: setpci reset kernel oops fix mpt3sas: Added OEM Gen2 PnP ID branding names mpt3sas: Refcount fw_events and fix unsafe list usage mpt3sas: Refcount sas_device objects and fix unsafe list usage mpt3sas: sysfs attribute to report Backup Rail Monitor Status mpt3sas: Ported WarpDrive product SSS6200 support mpt3sas: fix for driver fails EEH, recovery from injected pci bus error mpt3sas: Manage MSI-X vectors according to HBA device type ...
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
What: /sys/bus/scsi/drivers/st/debug_flag
|
||||
Date: October 2015
|
||||
Kernel Version: ?.?
|
||||
Contact: shane.seymour@hpe.com
|
||||
Description:
|
||||
This file allows you to turn debug output from the st driver
|
||||
off if you write a '0' to the file or on if you write a '1'.
|
||||
Note that debug output requires that the module be compiled
|
||||
with the #define DEBUG set to a non-zero value (this is the
|
||||
default). If DEBUG is set to 0 then this file will not
|
||||
appear in sysfs as its presence is conditional upon debug
|
||||
output support being compiled into the module.
|
||||
@@ -0,0 +1,58 @@
|
||||
* Qualcomm Technologies Inc Universal Flash Storage (UFS) PHY
|
||||
|
||||
UFSPHY nodes are defined to describe on-chip UFS PHY hardware macro.
|
||||
Each UFS PHY node should have its own node.
|
||||
|
||||
To bind UFS PHY with UFS host controller, the controller node should
|
||||
contain a phandle reference to UFS PHY node.
|
||||
|
||||
Required properties:
|
||||
- compatible : compatible list, contains "qcom,ufs-phy-qmp-20nm"
|
||||
or "qcom,ufs-phy-qmp-14nm" according to the relevant phy in use.
|
||||
- reg : should contain PHY register address space (mandatory),
|
||||
- reg-names : indicates various resources passed to driver (via reg proptery) by name.
|
||||
Required "reg-names" is "phy_mem".
|
||||
- #phy-cells : This property shall be set to 0
|
||||
- vdda-phy-supply : phandle to main PHY supply for analog domain
|
||||
- vdda-pll-supply : phandle to PHY PLL and Power-Gen block power supply
|
||||
- clocks : List of phandle and clock specifier pairs
|
||||
- clock-names : List of clock input name strings sorted in the same
|
||||
order as the clocks property. "ref_clk_src", "ref_clk",
|
||||
"tx_iface_clk" & "rx_iface_clk" are mandatory but
|
||||
"ref_clk_parent" is optional
|
||||
|
||||
Optional properties:
|
||||
- vdda-phy-max-microamp : specifies max. load that can be drawn from phy supply
|
||||
- vdda-pll-max-microamp : specifies max. load that can be drawn from pll supply
|
||||
- vddp-ref-clk-supply : phandle to UFS device ref_clk pad power supply
|
||||
- vddp-ref-clk-max-microamp : specifies max. load that can be drawn from this supply
|
||||
- vddp-ref-clk-always-on : specifies if this supply needs to be kept always on
|
||||
|
||||
Example:
|
||||
|
||||
ufsphy1: ufsphy@0xfc597000 {
|
||||
compatible = "qcom,ufs-phy-qmp-20nm";
|
||||
reg = <0xfc597000 0x800>;
|
||||
reg-names = "phy_mem";
|
||||
#phy-cells = <0>;
|
||||
vdda-phy-supply = <&pma8084_l4>;
|
||||
vdda-pll-supply = <&pma8084_l12>;
|
||||
vdda-phy-max-microamp = <50000>;
|
||||
vdda-pll-max-microamp = <1000>;
|
||||
clock-names = "ref_clk_src",
|
||||
"ref_clk_parent",
|
||||
"ref_clk",
|
||||
"tx_iface_clk",
|
||||
"rx_iface_clk";
|
||||
clocks = <&clock_rpm clk_ln_bb_clk>,
|
||||
<&clock_gcc clk_pcie_1_phy_ldo >,
|
||||
<&clock_gcc clk_ufs_phy_ldo>,
|
||||
<&clock_gcc clk_gcc_ufs_tx_cfg_clk>,
|
||||
<&clock_gcc clk_gcc_ufs_rx_cfg_clk>;
|
||||
};
|
||||
|
||||
ufshc@0xfc598000 {
|
||||
...
|
||||
phys = <&ufsphy1>;
|
||||
phy-names = "ufsphy";
|
||||
};
|
||||
@@ -4,11 +4,18 @@ UFSHC nodes are defined to describe on-chip UFS host controllers.
|
||||
Each UFS controller instance should have its own node.
|
||||
|
||||
Required properties:
|
||||
- compatible : compatible list, contains "jedec,ufs-1.1"
|
||||
- compatible : must contain "jedec,ufs-1.1", may also list one or more
|
||||
of the following:
|
||||
"qcom,msm8994-ufshc"
|
||||
"qcom,msm8996-ufshc"
|
||||
"qcom,ufshc"
|
||||
- interrupts : <interrupt mapping for UFS host controller IRQ>
|
||||
- reg : <registers mapping>
|
||||
|
||||
Optional properties:
|
||||
- phys : phandle to UFS PHY node
|
||||
- phy-names : the string "ufsphy" when is found in a node, along
|
||||
with "phys" attribute, provides phandle to UFS PHY node
|
||||
- vdd-hba-supply : phandle to UFS host controller supply regulator node
|
||||
- vcc-supply : phandle to VCC supply regulator node
|
||||
- vccq-supply : phandle to VCCQ supply regulator node
|
||||
@@ -54,4 +61,6 @@ Example:
|
||||
clocks = <&core 0>, <&ref 0>, <&iface 0>;
|
||||
clock-names = "core_clk", "ref_clk", "iface_clk";
|
||||
freq-table-hz = <100000000 200000000>, <0 0>, <0 0>;
|
||||
phys = <&ufsphy1>;
|
||||
phy-names = "ufsphy";
|
||||
};
|
||||
|
||||
@@ -569,7 +569,9 @@ Debugging code is now compiled in by default but debugging is turned off
|
||||
with the kernel module parameter debug_flag defaulting to 0. Debugging
|
||||
can still be switched on and off with an ioctl. To enable debug at
|
||||
module load time add debug_flag=1 to the module load options, the
|
||||
debugging output is not voluminous.
|
||||
debugging output is not voluminous. Debugging can also be enabled
|
||||
and disabled by writing a '0' (disable) or '1' (enable) to the sysfs
|
||||
file /sys/bus/scsi/drivers/st/debug_flag.
|
||||
|
||||
If the tape seems to hang, I would be very interested to hear where
|
||||
the driver is waiting. With the command 'ps -l' you can see the state
|
||||
|
||||
@@ -3696,9 +3696,6 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
|
||||
*/
|
||||
shost->max_host_blocked = 1;
|
||||
|
||||
if (scsi_init_shared_tag_map(shost, host->n_tags))
|
||||
goto err_add;
|
||||
|
||||
rc = scsi_add_host_with_dma(ap->scsi_host,
|
||||
&ap->tdev, ap->host->dev);
|
||||
if (rc)
|
||||
|
||||
@@ -2798,7 +2798,6 @@ static struct scsi_host_template srp_template = {
|
||||
.cmd_per_lun = SRP_DEFAULT_CMD_SQ_SIZE,
|
||||
.use_clustering = ENABLE_CLUSTERING,
|
||||
.shost_attrs = srp_host_attrs,
|
||||
.use_blk_tags = 1,
|
||||
.track_queue_depth = 1,
|
||||
};
|
||||
|
||||
@@ -3229,10 +3228,6 @@ static ssize_t srp_create_target(struct device *dev,
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = scsi_init_shared_tag_map(target_host, target_host->can_queue);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
target->req_ring_size = target->queue_size - SRP_TSK_MGMT_SQ_SIZE;
|
||||
|
||||
if (!srp_conn_unique(target->srp_host, target)) {
|
||||
|
||||
@@ -1038,6 +1038,10 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags,
|
||||
int i, buflist_ent;
|
||||
int sg_spill = MAX_FRAGS_SPILL1;
|
||||
int dir;
|
||||
|
||||
if (bytes < 0)
|
||||
return NULL;
|
||||
|
||||
/* initialization */
|
||||
*frags = 0;
|
||||
*blp = NULL;
|
||||
|
||||
@@ -1994,7 +1994,6 @@ static struct scsi_host_template mptsas_driver_template = {
|
||||
.cmd_per_lun = 7,
|
||||
.use_clustering = ENABLE_CLUSTERING,
|
||||
.shost_attrs = mptscsih_host_attrs,
|
||||
.use_blk_tags = 1,
|
||||
};
|
||||
|
||||
static int mptsas_get_linkerrors(struct sas_phy *phy)
|
||||
|
||||
@@ -325,7 +325,6 @@ NCR_700_detect(struct scsi_host_template *tpnt,
|
||||
tpnt->slave_destroy = NCR_700_slave_destroy;
|
||||
tpnt->slave_alloc = NCR_700_slave_alloc;
|
||||
tpnt->change_queue_depth = NCR_700_change_queue_depth;
|
||||
tpnt->use_blk_tags = 1;
|
||||
|
||||
if(tpnt->name == NULL)
|
||||
tpnt->name = "53c700";
|
||||
@@ -1107,7 +1106,9 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
|
||||
BUG();
|
||||
}
|
||||
if(hostdata->msgin[1] == A_SIMPLE_TAG_MSG) {
|
||||
struct scsi_cmnd *SCp = scsi_find_tag(SDp, hostdata->msgin[2]);
|
||||
struct scsi_cmnd *SCp;
|
||||
|
||||
SCp = scsi_host_find_tag(SDp->host, hostdata->msgin[2]);
|
||||
if(unlikely(SCp == NULL)) {
|
||||
printk(KERN_ERR "scsi%d: (%d:%d) no saved request for tag %d\n",
|
||||
host->host_no, reselection_id, lun, hostdata->msgin[2]);
|
||||
@@ -1119,7 +1120,9 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
|
||||
"reselection is tag %d, slot %p(%d)\n",
|
||||
hostdata->msgin[2], slot, slot->tag);
|
||||
} else {
|
||||
struct scsi_cmnd *SCp = scsi_find_tag(SDp, SCSI_NO_TAG);
|
||||
struct scsi_cmnd *SCp;
|
||||
|
||||
SCp = scsi_host_find_tag(SDp->host, SCSI_NO_TAG);
|
||||
if(unlikely(SCp == NULL)) {
|
||||
sdev_printk(KERN_ERR, SDp,
|
||||
"no saved request for untagged cmd\n");
|
||||
@@ -1823,7 +1826,7 @@ NCR_700_queuecommand_lck(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)
|
||||
slot->tag, slot);
|
||||
} else {
|
||||
slot->tag = SCSI_NO_TAG;
|
||||
/* must populate current_cmnd for scsi_find_tag to work */
|
||||
/* must populate current_cmnd for scsi_host_find_tag to work */
|
||||
SCp->device->current_cmnd = SCp;
|
||||
}
|
||||
/* sanity check: some of the commands generated by the mid-layer
|
||||
|
||||
@@ -2136,7 +2136,7 @@ static unsigned char FPT_SccbMgr_bad_isr(u32 p_port, unsigned char p_card,
|
||||
*
|
||||
*---------------------------------------------------------------------*/
|
||||
|
||||
static void FPT_SccbMgrTableInitAll()
|
||||
static void FPT_SccbMgrTableInitAll(void)
|
||||
{
|
||||
unsigned char thisCard;
|
||||
|
||||
|
||||
@@ -534,7 +534,6 @@ config SCSI_ARCMSR
|
||||
|
||||
source "drivers/scsi/esas2r/Kconfig"
|
||||
source "drivers/scsi/megaraid/Kconfig.megaraid"
|
||||
source "drivers/scsi/mpt2sas/Kconfig"
|
||||
source "drivers/scsi/mpt3sas/Kconfig"
|
||||
source "drivers/scsi/ufs/Kconfig"
|
||||
|
||||
|
||||
@@ -106,7 +106,6 @@ obj-$(CONFIG_CXLFLASH) += cxlflash/
|
||||
obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o
|
||||
obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/
|
||||
obj-$(CONFIG_MEGARAID_SAS) += megaraid/
|
||||
obj-$(CONFIG_SCSI_MPT2SAS) += mpt2sas/
|
||||
obj-$(CONFIG_SCSI_MPT3SAS) += mpt3sas/
|
||||
obj-$(CONFIG_SCSI_UFSHCD) += ufs/
|
||||
obj-$(CONFIG_SCSI_ACARD) += atp870u.o
|
||||
|
||||
+148
-133
@@ -259,7 +259,7 @@ MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the"
|
||||
" 0=off, 1=on");
|
||||
module_param_named(msi, aac_msi, int, S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(msi, "IRQ handling."
|
||||
" 0=PIC(default), 1=MSI, 2=MSI-X(unsupported, uses MSI)");
|
||||
" 0=PIC(default), 1=MSI, 2=MSI-X)");
|
||||
module_param(startup_timeout, int, S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(startup_timeout, "The duration of time in seconds to wait for"
|
||||
" adapter to have it's kernel up and\n"
|
||||
@@ -570,7 +570,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd)
|
||||
|
||||
status = aac_fib_send(ContainerCommand,
|
||||
cmd_fibcontext,
|
||||
sizeof (struct aac_get_name),
|
||||
sizeof(struct aac_get_name_resp),
|
||||
FsaNormal,
|
||||
0, 1,
|
||||
(fib_callback)get_container_name_callback,
|
||||
@@ -1052,7 +1052,7 @@ static int aac_get_container_serial(struct scsi_cmnd * scsicmd)
|
||||
|
||||
status = aac_fib_send(ContainerCommand,
|
||||
cmd_fibcontext,
|
||||
sizeof (struct aac_get_serial),
|
||||
sizeof(struct aac_get_serial_resp),
|
||||
FsaNormal,
|
||||
0, 1,
|
||||
(fib_callback) get_container_serial_callback,
|
||||
@@ -2977,11 +2977,16 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
|
||||
return;
|
||||
|
||||
BUG_ON(fibptr == NULL);
|
||||
|
||||
dev = fibptr->dev;
|
||||
|
||||
srbreply = (struct aac_srb_reply *) fib_data(fibptr);
|
||||
scsi_dma_unmap(scsicmd);
|
||||
|
||||
/* expose physical device if expose_physicald flag is on */
|
||||
if (scsicmd->cmnd[0] == INQUIRY && !(scsicmd->cmnd[1] & 0x01)
|
||||
&& expose_physicals > 0)
|
||||
aac_expose_phy_device(scsicmd);
|
||||
|
||||
srbreply = (struct aac_srb_reply *) fib_data(fibptr);
|
||||
scsicmd->sense_buffer[0] = '\0'; /* Initialize sense valid flag to false */
|
||||
|
||||
if (fibptr->flags & FIB_CONTEXT_FLAG_FASTRESP) {
|
||||
@@ -2994,147 +2999,157 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
|
||||
*/
|
||||
scsi_set_resid(scsicmd, scsi_bufflen(scsicmd)
|
||||
- le32_to_cpu(srbreply->data_xfer_length));
|
||||
}
|
||||
/*
|
||||
* First check the fib status
|
||||
*/
|
||||
|
||||
scsi_dma_unmap(scsicmd);
|
||||
if (le32_to_cpu(srbreply->status) != ST_OK) {
|
||||
int len;
|
||||
|
||||
/* expose physical device if expose_physicald flag is on */
|
||||
if (scsicmd->cmnd[0] == INQUIRY && !(scsicmd->cmnd[1] & 0x01)
|
||||
&& expose_physicals > 0)
|
||||
aac_expose_phy_device(scsicmd);
|
||||
printk(KERN_WARNING "aac_srb_callback: srb failed, status = %d\n", le32_to_cpu(srbreply->status));
|
||||
len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
|
||||
SCSI_SENSE_BUFFERSIZE);
|
||||
scsicmd->result = DID_ERROR << 16
|
||||
| COMMAND_COMPLETE << 8
|
||||
| SAM_STAT_CHECK_CONDITION;
|
||||
memcpy(scsicmd->sense_buffer,
|
||||
srbreply->sense_data, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* First check the fib status
|
||||
*/
|
||||
|
||||
if (le32_to_cpu(srbreply->status) != ST_OK){
|
||||
int len;
|
||||
printk(KERN_WARNING "aac_srb_callback: srb failed, status = %d\n", le32_to_cpu(srbreply->status));
|
||||
len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
|
||||
SCSI_SENSE_BUFFERSIZE);
|
||||
scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
|
||||
memcpy(scsicmd->sense_buffer, srbreply->sense_data, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Next check the srb status
|
||||
*/
|
||||
switch( (le32_to_cpu(srbreply->srb_status))&0x3f){
|
||||
case SRB_STATUS_ERROR_RECOVERY:
|
||||
case SRB_STATUS_PENDING:
|
||||
case SRB_STATUS_SUCCESS:
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
case SRB_STATUS_DATA_OVERRUN:
|
||||
switch(scsicmd->cmnd[0]){
|
||||
case READ_6:
|
||||
case WRITE_6:
|
||||
case READ_10:
|
||||
case WRITE_10:
|
||||
case READ_12:
|
||||
case WRITE_12:
|
||||
case READ_16:
|
||||
case WRITE_16:
|
||||
if (le32_to_cpu(srbreply->data_xfer_length) < scsicmd->underflow) {
|
||||
printk(KERN_WARNING"aacraid: SCSI CMD underflow\n");
|
||||
} else {
|
||||
printk(KERN_WARNING"aacraid: SCSI CMD Data Overrun\n");
|
||||
}
|
||||
scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
case INQUIRY: {
|
||||
/*
|
||||
* Next check the srb status
|
||||
*/
|
||||
switch ((le32_to_cpu(srbreply->srb_status))&0x3f) {
|
||||
case SRB_STATUS_ERROR_RECOVERY:
|
||||
case SRB_STATUS_PENDING:
|
||||
case SRB_STATUS_SUCCESS:
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SRB_STATUS_ABORTED:
|
||||
scsicmd->result = DID_ABORT << 16 | ABORT << 8;
|
||||
break;
|
||||
case SRB_STATUS_ABORT_FAILED:
|
||||
// Not sure about this one - but assuming the hba was trying to abort for some reason
|
||||
scsicmd->result = DID_ERROR << 16 | ABORT << 8;
|
||||
break;
|
||||
case SRB_STATUS_PARITY_ERROR:
|
||||
scsicmd->result = DID_PARITY << 16 | MSG_PARITY_ERROR << 8;
|
||||
break;
|
||||
case SRB_STATUS_NO_DEVICE:
|
||||
case SRB_STATUS_INVALID_PATH_ID:
|
||||
case SRB_STATUS_INVALID_TARGET_ID:
|
||||
case SRB_STATUS_INVALID_LUN:
|
||||
case SRB_STATUS_SELECTION_TIMEOUT:
|
||||
scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
|
||||
case SRB_STATUS_COMMAND_TIMEOUT:
|
||||
case SRB_STATUS_TIMEOUT:
|
||||
scsicmd->result = DID_TIME_OUT << 16 | COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
|
||||
case SRB_STATUS_BUSY:
|
||||
scsicmd->result = DID_BUS_BUSY << 16 | COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
|
||||
case SRB_STATUS_BUS_RESET:
|
||||
scsicmd->result = DID_RESET << 16 | COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
|
||||
case SRB_STATUS_MESSAGE_REJECTED:
|
||||
scsicmd->result = DID_ERROR << 16 | MESSAGE_REJECT << 8;
|
||||
break;
|
||||
case SRB_STATUS_REQUEST_FLUSHED:
|
||||
case SRB_STATUS_ERROR:
|
||||
case SRB_STATUS_INVALID_REQUEST:
|
||||
case SRB_STATUS_REQUEST_SENSE_FAILED:
|
||||
case SRB_STATUS_NO_HBA:
|
||||
case SRB_STATUS_UNEXPECTED_BUS_FREE:
|
||||
case SRB_STATUS_PHASE_SEQUENCE_FAILURE:
|
||||
case SRB_STATUS_BAD_SRB_BLOCK_LENGTH:
|
||||
case SRB_STATUS_DELAYED_RETRY:
|
||||
case SRB_STATUS_BAD_FUNCTION:
|
||||
case SRB_STATUS_NOT_STARTED:
|
||||
case SRB_STATUS_NOT_IN_USE:
|
||||
case SRB_STATUS_FORCE_ABORT:
|
||||
case SRB_STATUS_DOMAIN_VALIDATION_FAIL:
|
||||
default:
|
||||
#ifdef AAC_DETAILED_STATUS_INFO
|
||||
printk("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n",
|
||||
le32_to_cpu(srbreply->srb_status) & 0x3F,
|
||||
aac_get_status_string(
|
||||
le32_to_cpu(srbreply->srb_status) & 0x3F),
|
||||
scsicmd->cmnd[0],
|
||||
le32_to_cpu(srbreply->scsi_status));
|
||||
#endif
|
||||
if ((scsicmd->cmnd[0] == ATA_12)
|
||||
|| (scsicmd->cmnd[0] == ATA_16)) {
|
||||
if (scsicmd->cmnd[2] & (0x01 << 5)) {
|
||||
scsicmd->result = DID_OK << 16
|
||||
| COMMAND_COMPLETE << 8;
|
||||
case SRB_STATUS_DATA_OVERRUN:
|
||||
switch (scsicmd->cmnd[0]) {
|
||||
case READ_6:
|
||||
case WRITE_6:
|
||||
case READ_10:
|
||||
case WRITE_10:
|
||||
case READ_12:
|
||||
case WRITE_12:
|
||||
case READ_16:
|
||||
case WRITE_16:
|
||||
if (le32_to_cpu(srbreply->data_xfer_length)
|
||||
< scsicmd->underflow)
|
||||
printk(KERN_WARNING"aacraid: SCSI CMD underflow\n");
|
||||
else
|
||||
printk(KERN_WARNING"aacraid: SCSI CMD Data Overrun\n");
|
||||
scsicmd->result = DID_ERROR << 16
|
||||
| COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
case INQUIRY: {
|
||||
scsicmd->result = DID_OK << 16
|
||||
| COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SRB_STATUS_ABORTED:
|
||||
scsicmd->result = DID_ABORT << 16 | ABORT << 8;
|
||||
break;
|
||||
case SRB_STATUS_ABORT_FAILED:
|
||||
/*
|
||||
* Not sure about this one - but assuming the
|
||||
* hba was trying to abort for some reason
|
||||
*/
|
||||
scsicmd->result = DID_ERROR << 16 | ABORT << 8;
|
||||
break;
|
||||
case SRB_STATUS_PARITY_ERROR:
|
||||
scsicmd->result = DID_PARITY << 16
|
||||
| MSG_PARITY_ERROR << 8;
|
||||
break;
|
||||
case SRB_STATUS_NO_DEVICE:
|
||||
case SRB_STATUS_INVALID_PATH_ID:
|
||||
case SRB_STATUS_INVALID_TARGET_ID:
|
||||
case SRB_STATUS_INVALID_LUN:
|
||||
case SRB_STATUS_SELECTION_TIMEOUT:
|
||||
scsicmd->result = DID_NO_CONNECT << 16
|
||||
| COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
|
||||
case SRB_STATUS_COMMAND_TIMEOUT:
|
||||
case SRB_STATUS_TIMEOUT:
|
||||
scsicmd->result = DID_TIME_OUT << 16
|
||||
| COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
|
||||
case SRB_STATUS_BUSY:
|
||||
scsicmd->result = DID_BUS_BUSY << 16
|
||||
| COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
|
||||
case SRB_STATUS_BUS_RESET:
|
||||
scsicmd->result = DID_RESET << 16
|
||||
| COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
|
||||
case SRB_STATUS_MESSAGE_REJECTED:
|
||||
scsicmd->result = DID_ERROR << 16
|
||||
| MESSAGE_REJECT << 8;
|
||||
break;
|
||||
case SRB_STATUS_REQUEST_FLUSHED:
|
||||
case SRB_STATUS_ERROR:
|
||||
case SRB_STATUS_INVALID_REQUEST:
|
||||
case SRB_STATUS_REQUEST_SENSE_FAILED:
|
||||
case SRB_STATUS_NO_HBA:
|
||||
case SRB_STATUS_UNEXPECTED_BUS_FREE:
|
||||
case SRB_STATUS_PHASE_SEQUENCE_FAILURE:
|
||||
case SRB_STATUS_BAD_SRB_BLOCK_LENGTH:
|
||||
case SRB_STATUS_DELAYED_RETRY:
|
||||
case SRB_STATUS_BAD_FUNCTION:
|
||||
case SRB_STATUS_NOT_STARTED:
|
||||
case SRB_STATUS_NOT_IN_USE:
|
||||
case SRB_STATUS_FORCE_ABORT:
|
||||
case SRB_STATUS_DOMAIN_VALIDATION_FAIL:
|
||||
default:
|
||||
#ifdef AAC_DETAILED_STATUS_INFO
|
||||
printk(KERN_INFO "aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n",
|
||||
le32_to_cpu(srbreply->srb_status) & 0x3F,
|
||||
aac_get_status_string(
|
||||
le32_to_cpu(srbreply->srb_status) & 0x3F),
|
||||
scsicmd->cmnd[0],
|
||||
le32_to_cpu(srbreply->scsi_status));
|
||||
#endif
|
||||
if ((scsicmd->cmnd[0] == ATA_12)
|
||||
|| (scsicmd->cmnd[0] == ATA_16)) {
|
||||
if (scsicmd->cmnd[2] & (0x01 << 5)) {
|
||||
scsicmd->result = DID_OK << 16
|
||||
| COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
} else {
|
||||
scsicmd->result = DID_ERROR << 16
|
||||
| COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
scsicmd->result = DID_ERROR << 16
|
||||
| COMMAND_COMPLETE << 8;
|
||||
| COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
scsicmd->result = DID_ERROR << 16
|
||||
| COMMAND_COMPLETE << 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (le32_to_cpu(srbreply->scsi_status) == SAM_STAT_CHECK_CONDITION) {
|
||||
int len;
|
||||
scsicmd->result |= SAM_STAT_CHECK_CONDITION;
|
||||
len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
|
||||
SCSI_SENSE_BUFFERSIZE);
|
||||
if (le32_to_cpu(srbreply->scsi_status)
|
||||
== SAM_STAT_CHECK_CONDITION) {
|
||||
int len;
|
||||
|
||||
scsicmd->result |= SAM_STAT_CHECK_CONDITION;
|
||||
len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
|
||||
SCSI_SENSE_BUFFERSIZE);
|
||||
#ifdef AAC_DETAILED_STATUS_INFO
|
||||
printk(KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n",
|
||||
le32_to_cpu(srbreply->status), len);
|
||||
printk(KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n",
|
||||
le32_to_cpu(srbreply->status), len);
|
||||
#endif
|
||||
memcpy(scsicmd->sense_buffer, srbreply->sense_data, len);
|
||||
memcpy(scsicmd->sense_buffer,
|
||||
srbreply->sense_data, len);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* OR in the scsi status (already shifted up a bit)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* D E F I N E S
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#define AAC_MAX_MSIX 8 /* vectors */
|
||||
#define AAC_MAX_MSIX 32 /* vectors */
|
||||
#define AAC_PCI_MSI_ENABLE 0x8000
|
||||
|
||||
enum {
|
||||
@@ -62,7 +62,7 @@ enum {
|
||||
#define PMC_GLOBAL_INT_BIT0 0x00000001
|
||||
|
||||
#ifndef AAC_DRIVER_BUILD
|
||||
# define AAC_DRIVER_BUILD 40709
|
||||
# define AAC_DRIVER_BUILD 41010
|
||||
# define AAC_DRIVER_BRANCH "-ms"
|
||||
#endif
|
||||
#define MAXIMUM_NUM_CONTAINERS 32
|
||||
@@ -547,6 +547,7 @@ struct adapter_ops
|
||||
int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4);
|
||||
int (*adapter_check_health)(struct aac_dev *dev);
|
||||
int (*adapter_restart)(struct aac_dev *dev, int bled);
|
||||
void (*adapter_start)(struct aac_dev *dev);
|
||||
/* Transport operations */
|
||||
int (*adapter_ioremap)(struct aac_dev * dev, u32 size);
|
||||
irq_handler_t adapter_intr;
|
||||
@@ -843,6 +844,10 @@ struct src_registers {
|
||||
&((AEP)->regs.src.bar0->CSR))
|
||||
#define src_writel(AEP, CSR, value) writel(value, \
|
||||
&((AEP)->regs.src.bar0->CSR))
|
||||
#if defined(writeq)
|
||||
#define src_writeq(AEP, CSR, value) writeq(value, \
|
||||
&((AEP)->regs.src.bar0->CSR))
|
||||
#endif
|
||||
|
||||
#define SRC_ODR_SHIFT 12
|
||||
#define SRC_IDR_SHIFT 9
|
||||
@@ -1162,6 +1167,11 @@ struct aac_dev
|
||||
struct fsa_dev_info *fsa_dev;
|
||||
struct task_struct *thread;
|
||||
int cardtype;
|
||||
/*
|
||||
*This lock will protect the two 32-bit
|
||||
*writes to the Inbound Queue
|
||||
*/
|
||||
spinlock_t iq_lock;
|
||||
|
||||
/*
|
||||
* The following is the device specific extension.
|
||||
@@ -1247,6 +1257,9 @@ struct aac_dev
|
||||
#define aac_adapter_restart(dev,bled) \
|
||||
(dev)->a_ops.adapter_restart(dev,bled)
|
||||
|
||||
#define aac_adapter_start(dev) \
|
||||
((dev)->a_ops.adapter_start(dev))
|
||||
|
||||
#define aac_adapter_ioremap(dev, size) \
|
||||
(dev)->a_ops.adapter_ioremap(dev, size)
|
||||
|
||||
@@ -2097,6 +2110,8 @@ static inline unsigned int cap_to_cyls(sector_t capacity, unsigned divisor)
|
||||
#define AAC_OWNER_ERROR_HANDLER 0x103
|
||||
#define AAC_OWNER_FIRMWARE 0x106
|
||||
|
||||
int aac_acquire_irq(struct aac_dev *dev);
|
||||
void aac_free_irq(struct aac_dev *dev);
|
||||
const char *aac_driverinfo(struct Scsi_Host *);
|
||||
struct fib *aac_fib_alloc(struct aac_dev *dev);
|
||||
int aac_fib_setup(struct aac_dev *dev);
|
||||
@@ -2127,6 +2142,7 @@ int aac_sa_init(struct aac_dev *dev);
|
||||
int aac_src_init(struct aac_dev *dev);
|
||||
int aac_srcv_init(struct aac_dev *dev);
|
||||
int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify);
|
||||
void aac_define_int_mode(struct aac_dev *dev);
|
||||
unsigned int aac_response_normal(struct aac_queue * q);
|
||||
unsigned int aac_command_normal(struct aac_queue * q);
|
||||
unsigned int aac_intr_normal(struct aac_dev *dev, u32 Index,
|
||||
|
||||
@@ -43,8 +43,6 @@
|
||||
|
||||
#include "aacraid.h"
|
||||
|
||||
static void aac_define_int_mode(struct aac_dev *dev);
|
||||
|
||||
struct aac_common aac_config = {
|
||||
.irq_mod = 1
|
||||
};
|
||||
@@ -338,6 +336,74 @@ static int aac_comm_init(struct aac_dev * dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void aac_define_int_mode(struct aac_dev *dev)
|
||||
{
|
||||
int i, msi_count, min_msix;
|
||||
|
||||
msi_count = i = 0;
|
||||
/* max. vectors from GET_COMM_PREFERRED_SETTINGS */
|
||||
if (dev->max_msix == 0 ||
|
||||
dev->pdev->device == PMC_DEVICE_S6 ||
|
||||
dev->sync_mode) {
|
||||
dev->max_msix = 1;
|
||||
dev->vector_cap =
|
||||
dev->scsi_host_ptr->can_queue +
|
||||
AAC_NUM_MGT_FIB;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Don't bother allocating more MSI-X vectors than cpus */
|
||||
msi_count = min(dev->max_msix,
|
||||
(unsigned int)num_online_cpus());
|
||||
|
||||
dev->max_msix = msi_count;
|
||||
|
||||
if (msi_count > AAC_MAX_MSIX)
|
||||
msi_count = AAC_MAX_MSIX;
|
||||
|
||||
for (i = 0; i < msi_count; i++)
|
||||
dev->msixentry[i].entry = i;
|
||||
|
||||
if (msi_count > 1 &&
|
||||
pci_find_capability(dev->pdev, PCI_CAP_ID_MSIX)) {
|
||||
min_msix = 2;
|
||||
i = pci_enable_msix_range(dev->pdev,
|
||||
dev->msixentry,
|
||||
min_msix,
|
||||
msi_count);
|
||||
if (i > 0) {
|
||||
dev->msi_enabled = 1;
|
||||
msi_count = i;
|
||||
} else {
|
||||
dev->msi_enabled = 0;
|
||||
printk(KERN_ERR "%s%d: MSIX not supported!! Will try MSI 0x%x.\n",
|
||||
dev->name, dev->id, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (!dev->msi_enabled) {
|
||||
msi_count = 1;
|
||||
i = pci_enable_msi(dev->pdev);
|
||||
|
||||
if (!i) {
|
||||
dev->msi_enabled = 1;
|
||||
dev->msi = 1;
|
||||
} else {
|
||||
printk(KERN_ERR "%s%d: MSI not supported!! Will try INTx 0x%x.\n",
|
||||
dev->name, dev->id, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (!dev->msi_enabled)
|
||||
dev->max_msix = msi_count = 1;
|
||||
else {
|
||||
if (dev->max_msix > msi_count)
|
||||
dev->max_msix = msi_count;
|
||||
}
|
||||
dev->vector_cap =
|
||||
(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) /
|
||||
msi_count;
|
||||
}
|
||||
struct aac_dev *aac_init_adapter(struct aac_dev *dev)
|
||||
{
|
||||
u32 status[5];
|
||||
@@ -350,6 +416,7 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
|
||||
dev->management_fib_count = 0;
|
||||
spin_lock_init(&dev->manage_lock);
|
||||
spin_lock_init(&dev->sync_lock);
|
||||
spin_lock_init(&dev->iq_lock);
|
||||
dev->max_fib_size = sizeof(struct hw_fib);
|
||||
dev->sg_tablesize = host->sg_tablesize = (dev->max_fib_size
|
||||
- sizeof(struct aac_fibhdr)
|
||||
@@ -508,79 +575,3 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
|
||||
return dev;
|
||||
}
|
||||
|
||||
static void aac_define_int_mode(struct aac_dev *dev)
|
||||
{
|
||||
|
||||
int i, msi_count;
|
||||
|
||||
msi_count = i = 0;
|
||||
/* max. vectors from GET_COMM_PREFERRED_SETTINGS */
|
||||
if (dev->max_msix == 0 ||
|
||||
dev->pdev->device == PMC_DEVICE_S6 ||
|
||||
dev->sync_mode) {
|
||||
dev->max_msix = 1;
|
||||
dev->vector_cap =
|
||||
dev->scsi_host_ptr->can_queue +
|
||||
AAC_NUM_MGT_FIB;
|
||||
return;
|
||||
}
|
||||
|
||||
msi_count = min(dev->max_msix,
|
||||
(unsigned int)num_online_cpus());
|
||||
|
||||
dev->max_msix = msi_count;
|
||||
|
||||
if (msi_count > AAC_MAX_MSIX)
|
||||
msi_count = AAC_MAX_MSIX;
|
||||
|
||||
for (i = 0; i < msi_count; i++)
|
||||
dev->msixentry[i].entry = i;
|
||||
|
||||
if (msi_count > 1 &&
|
||||
pci_find_capability(dev->pdev, PCI_CAP_ID_MSIX)) {
|
||||
i = pci_enable_msix(dev->pdev,
|
||||
dev->msixentry,
|
||||
msi_count);
|
||||
/* Check how many MSIX vectors are allocated */
|
||||
if (i >= 0) {
|
||||
dev->msi_enabled = 1;
|
||||
if (i) {
|
||||
msi_count = i;
|
||||
if (pci_enable_msix(dev->pdev,
|
||||
dev->msixentry,
|
||||
msi_count)) {
|
||||
dev->msi_enabled = 0;
|
||||
printk(KERN_ERR "%s%d: MSIX not supported!! Will try MSI 0x%x.\n",
|
||||
dev->name, dev->id, i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dev->msi_enabled = 0;
|
||||
printk(KERN_ERR "%s%d: MSIX not supported!! Will try MSI 0x%x.\n",
|
||||
dev->name, dev->id, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (!dev->msi_enabled) {
|
||||
msi_count = 1;
|
||||
i = pci_enable_msi(dev->pdev);
|
||||
|
||||
if (!i) {
|
||||
dev->msi_enabled = 1;
|
||||
dev->msi = 1;
|
||||
} else {
|
||||
printk(KERN_ERR "%s%d: MSI not supported!! Will try INTx 0x%x.\n",
|
||||
dev->name, dev->id, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (!dev->msi_enabled)
|
||||
dev->max_msix = msi_count = 1;
|
||||
else {
|
||||
if (dev->max_msix > msi_count)
|
||||
dev->max_msix = msi_count;
|
||||
}
|
||||
dev->vector_cap =
|
||||
(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) /
|
||||
msi_count;
|
||||
}
|
||||
|
||||
@@ -1270,13 +1270,12 @@ retry_next:
|
||||
static int _aac_reset_adapter(struct aac_dev *aac, int forced)
|
||||
{
|
||||
int index, quirks;
|
||||
int retval, i;
|
||||
int retval;
|
||||
struct Scsi_Host *host;
|
||||
struct scsi_device *dev;
|
||||
struct scsi_cmnd *command;
|
||||
struct scsi_cmnd *command_list;
|
||||
int jafo = 0;
|
||||
int cpu;
|
||||
|
||||
/*
|
||||
* Assumptions:
|
||||
@@ -1339,35 +1338,7 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced)
|
||||
aac->comm_phys = 0;
|
||||
kfree(aac->queues);
|
||||
aac->queues = NULL;
|
||||
cpu = cpumask_first(cpu_online_mask);
|
||||
if (aac->pdev->device == PMC_DEVICE_S6 ||
|
||||
aac->pdev->device == PMC_DEVICE_S7 ||
|
||||
aac->pdev->device == PMC_DEVICE_S8 ||
|
||||
aac->pdev->device == PMC_DEVICE_S9) {
|
||||
if (aac->max_msix > 1) {
|
||||
for (i = 0; i < aac->max_msix; i++) {
|
||||
if (irq_set_affinity_hint(
|
||||
aac->msixentry[i].vector,
|
||||
NULL)) {
|
||||
printk(KERN_ERR "%s%d: Failed to reset IRQ affinity for cpu %d\n",
|
||||
aac->name,
|
||||
aac->id,
|
||||
cpu);
|
||||
}
|
||||
cpu = cpumask_next(cpu,
|
||||
cpu_online_mask);
|
||||
free_irq(aac->msixentry[i].vector,
|
||||
&(aac->aac_msix[i]));
|
||||
}
|
||||
pci_disable_msix(aac->pdev);
|
||||
} else {
|
||||
free_irq(aac->pdev->irq, &(aac->aac_msix[0]));
|
||||
}
|
||||
} else {
|
||||
free_irq(aac->pdev->irq, aac);
|
||||
}
|
||||
if (aac->msi)
|
||||
pci_disable_msi(aac->pdev);
|
||||
aac_free_irq(aac);
|
||||
kfree(aac->fsa_dev);
|
||||
aac->fsa_dev = NULL;
|
||||
quirks = aac_get_driver_ident(index)->quirks;
|
||||
@@ -1978,3 +1949,83 @@ int aac_command_thread(void *data)
|
||||
dev->aif_thread = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aac_acquire_irq(struct aac_dev *dev)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int ret = 0;
|
||||
int cpu;
|
||||
|
||||
cpu = cpumask_first(cpu_online_mask);
|
||||
if (!dev->sync_mode && dev->msi_enabled && dev->max_msix > 1) {
|
||||
for (i = 0; i < dev->max_msix; i++) {
|
||||
dev->aac_msix[i].vector_no = i;
|
||||
dev->aac_msix[i].dev = dev;
|
||||
if (request_irq(dev->msixentry[i].vector,
|
||||
dev->a_ops.adapter_intr,
|
||||
0, "aacraid", &(dev->aac_msix[i]))) {
|
||||
printk(KERN_ERR "%s%d: Failed to register IRQ for vector %d.\n",
|
||||
dev->name, dev->id, i);
|
||||
for (j = 0 ; j < i ; j++)
|
||||
free_irq(dev->msixentry[j].vector,
|
||||
&(dev->aac_msix[j]));
|
||||
pci_disable_msix(dev->pdev);
|
||||
ret = -1;
|
||||
}
|
||||
if (irq_set_affinity_hint(dev->msixentry[i].vector,
|
||||
get_cpu_mask(cpu))) {
|
||||
printk(KERN_ERR "%s%d: Failed to set IRQ affinity for cpu %d\n",
|
||||
dev->name, dev->id, cpu);
|
||||
}
|
||||
cpu = cpumask_next(cpu, cpu_online_mask);
|
||||
}
|
||||
} else {
|
||||
dev->aac_msix[0].vector_no = 0;
|
||||
dev->aac_msix[0].dev = dev;
|
||||
|
||||
if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
|
||||
IRQF_SHARED, "aacraid",
|
||||
&(dev->aac_msix[0])) < 0) {
|
||||
if (dev->msi)
|
||||
pci_disable_msi(dev->pdev);
|
||||
printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
|
||||
dev->name, dev->id);
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void aac_free_irq(struct aac_dev *dev)
|
||||
{
|
||||
int i;
|
||||
int cpu;
|
||||
|
||||
cpu = cpumask_first(cpu_online_mask);
|
||||
if (dev->pdev->device == PMC_DEVICE_S6 ||
|
||||
dev->pdev->device == PMC_DEVICE_S7 ||
|
||||
dev->pdev->device == PMC_DEVICE_S8 ||
|
||||
dev->pdev->device == PMC_DEVICE_S9) {
|
||||
if (dev->max_msix > 1) {
|
||||
for (i = 0; i < dev->max_msix; i++) {
|
||||
if (irq_set_affinity_hint(
|
||||
dev->msixentry[i].vector, NULL)) {
|
||||
printk(KERN_ERR "%s%d: Failed to reset IRQ affinity for cpu %d\n",
|
||||
dev->name, dev->id, cpu);
|
||||
}
|
||||
cpu = cpumask_next(cpu, cpu_online_mask);
|
||||
free_irq(dev->msixentry[i].vector,
|
||||
&(dev->aac_msix[i]));
|
||||
}
|
||||
} else {
|
||||
free_irq(dev->pdev->irq, &(dev->aac_msix[0]));
|
||||
}
|
||||
} else {
|
||||
free_irq(dev->pdev->irq, dev);
|
||||
}
|
||||
if (dev->msi)
|
||||
pci_disable_msi(dev->pdev);
|
||||
else if (dev->max_msix > 1)
|
||||
pci_disable_msix(dev->pdev);
|
||||
}
|
||||
|
||||
@@ -1317,6 +1317,154 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
return error;
|
||||
}
|
||||
|
||||
#if (defined(CONFIG_PM))
|
||||
void aac_release_resources(struct aac_dev *aac)
|
||||
{
|
||||
int i;
|
||||
|
||||
aac_adapter_disable_int(aac);
|
||||
if (aac->pdev->device == PMC_DEVICE_S6 ||
|
||||
aac->pdev->device == PMC_DEVICE_S7 ||
|
||||
aac->pdev->device == PMC_DEVICE_S8 ||
|
||||
aac->pdev->device == PMC_DEVICE_S9) {
|
||||
if (aac->max_msix > 1) {
|
||||
for (i = 0; i < aac->max_msix; i++)
|
||||
free_irq(aac->msixentry[i].vector,
|
||||
&(aac->aac_msix[i]));
|
||||
} else {
|
||||
free_irq(aac->pdev->irq, &(aac->aac_msix[0]));
|
||||
}
|
||||
} else {
|
||||
free_irq(aac->pdev->irq, aac);
|
||||
}
|
||||
if (aac->msi)
|
||||
pci_disable_msi(aac->pdev);
|
||||
else if (aac->max_msix > 1)
|
||||
pci_disable_msix(aac->pdev);
|
||||
|
||||
}
|
||||
|
||||
static int aac_acquire_resources(struct aac_dev *dev)
|
||||
{
|
||||
int i, j;
|
||||
int instance = dev->id;
|
||||
const char *name = dev->name;
|
||||
unsigned long status;
|
||||
/*
|
||||
* First clear out all interrupts. Then enable the one's that we
|
||||
* can handle.
|
||||
*/
|
||||
while (!((status = src_readl(dev, MUnit.OMR)) & KERNEL_UP_AND_RUNNING)
|
||||
|| status == 0xffffffff)
|
||||
msleep(20);
|
||||
|
||||
aac_adapter_disable_int(dev);
|
||||
aac_adapter_enable_int(dev);
|
||||
|
||||
|
||||
if ((dev->pdev->device == PMC_DEVICE_S7 ||
|
||||
dev->pdev->device == PMC_DEVICE_S8 ||
|
||||
dev->pdev->device == PMC_DEVICE_S9))
|
||||
aac_define_int_mode(dev);
|
||||
|
||||
if (dev->msi_enabled)
|
||||
aac_src_access_devreg(dev, AAC_ENABLE_MSIX);
|
||||
|
||||
if (!dev->sync_mode && dev->msi_enabled && dev->max_msix > 1) {
|
||||
for (i = 0; i < dev->max_msix; i++) {
|
||||
dev->aac_msix[i].vector_no = i;
|
||||
dev->aac_msix[i].dev = dev;
|
||||
|
||||
if (request_irq(dev->msixentry[i].vector,
|
||||
dev->a_ops.adapter_intr,
|
||||
0, "aacraid", &(dev->aac_msix[i]))) {
|
||||
printk(KERN_ERR "%s%d: Failed to register IRQ for vector %d.\n",
|
||||
name, instance, i);
|
||||
for (j = 0 ; j < i ; j++)
|
||||
free_irq(dev->msixentry[j].vector,
|
||||
&(dev->aac_msix[j]));
|
||||
pci_disable_msix(dev->pdev);
|
||||
goto error_iounmap;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dev->aac_msix[0].vector_no = 0;
|
||||
dev->aac_msix[0].dev = dev;
|
||||
|
||||
if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
|
||||
IRQF_SHARED, "aacraid",
|
||||
&(dev->aac_msix[0])) < 0) {
|
||||
if (dev->msi)
|
||||
pci_disable_msi(dev->pdev);
|
||||
printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
|
||||
name, instance);
|
||||
goto error_iounmap;
|
||||
}
|
||||
}
|
||||
|
||||
aac_adapter_enable_int(dev);
|
||||
|
||||
if (!dev->sync_mode)
|
||||
aac_adapter_start(dev);
|
||||
return 0;
|
||||
|
||||
error_iounmap:
|
||||
return -1;
|
||||
|
||||
}
|
||||
static int aac_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
{
|
||||
|
||||
struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
||||
struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
|
||||
|
||||
scsi_block_requests(shost);
|
||||
aac_send_shutdown(aac);
|
||||
|
||||
aac_release_resources(aac);
|
||||
|
||||
pci_set_drvdata(pdev, shost);
|
||||
pci_save_state(pdev);
|
||||
pci_disable_device(pdev);
|
||||
pci_set_power_state(pdev, pci_choose_state(pdev, state));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aac_resume(struct pci_dev *pdev)
|
||||
{
|
||||
struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
||||
struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
|
||||
int r;
|
||||
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
pci_enable_wake(pdev, PCI_D0, 0);
|
||||
pci_restore_state(pdev);
|
||||
r = pci_enable_device(pdev);
|
||||
|
||||
if (r)
|
||||
goto fail_device;
|
||||
|
||||
pci_set_master(pdev);
|
||||
if (aac_acquire_resources(aac))
|
||||
goto fail_device;
|
||||
/*
|
||||
* reset this flag to unblock ioctl() as it was set at
|
||||
* aac_send_shutdown() to block ioctls from upperlayer
|
||||
*/
|
||||
aac->adapter_shutdown = 0;
|
||||
scsi_unblock_requests(shost);
|
||||
|
||||
return 0;
|
||||
|
||||
fail_device:
|
||||
printk(KERN_INFO "%s%d: resume failed.\n", aac->name, aac->id);
|
||||
scsi_host_put(shost);
|
||||
pci_disable_device(pdev);
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void aac_shutdown(struct pci_dev *dev)
|
||||
{
|
||||
struct Scsi_Host *shost = pci_get_drvdata(dev);
|
||||
@@ -1356,6 +1504,10 @@ static struct pci_driver aac_pci_driver = {
|
||||
.id_table = aac_pci_tbl,
|
||||
.probe = aac_probe_one,
|
||||
.remove = aac_remove_one,
|
||||
#if (defined(CONFIG_PM))
|
||||
.suspend = aac_suspend,
|
||||
.resume = aac_resume,
|
||||
#endif
|
||||
.shutdown = aac_shutdown,
|
||||
};
|
||||
|
||||
|
||||
@@ -623,6 +623,7 @@ int _aac_rx_init(struct aac_dev *dev)
|
||||
dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
|
||||
dev->a_ops.adapter_check_health = aac_rx_check_health;
|
||||
dev->a_ops.adapter_restart = aac_rx_restart_adapter;
|
||||
dev->a_ops.adapter_start = aac_rx_start_adapter;
|
||||
|
||||
/*
|
||||
* First clear out all interrupts. Then enable the one's that we
|
||||
|
||||
@@ -372,6 +372,7 @@ int aac_sa_init(struct aac_dev *dev)
|
||||
dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
|
||||
dev->a_ops.adapter_check_health = aac_sa_check_health;
|
||||
dev->a_ops.adapter_restart = aac_sa_restart_adapter;
|
||||
dev->a_ops.adapter_start = aac_sa_start_adapter;
|
||||
dev->a_ops.adapter_intr = aac_sa_intr;
|
||||
dev->a_ops.adapter_deliver = aac_rx_deliver_producer;
|
||||
dev->a_ops.adapter_ioremap = aac_sa_ioremap;
|
||||
|
||||
+15
-45
@@ -447,6 +447,10 @@ static int aac_src_deliver_message(struct fib *fib)
|
||||
u32 fibsize;
|
||||
dma_addr_t address;
|
||||
struct aac_fib_xporthdr *pFibX;
|
||||
#if !defined(writeq)
|
||||
unsigned long flags;
|
||||
#endif
|
||||
|
||||
u16 hdr_size = le16_to_cpu(fib->hw_fib_va->header.Size);
|
||||
|
||||
atomic_inc(&q->numpending);
|
||||
@@ -511,10 +515,14 @@ static int aac_src_deliver_message(struct fib *fib)
|
||||
return -EINVAL;
|
||||
address |= fibsize;
|
||||
}
|
||||
|
||||
#if defined(writeq)
|
||||
src_writeq(dev, MUnit.IQ_L, (u64)address);
|
||||
#else
|
||||
spin_lock_irqsave(&fib->dev->iq_lock, flags);
|
||||
src_writel(dev, MUnit.IQ_H, upper_32_bits(address) & 0xffffffff);
|
||||
src_writel(dev, MUnit.IQ_L, address & 0xffffffff);
|
||||
|
||||
spin_unlock_irqrestore(&fib->dev->iq_lock, flags);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -726,6 +734,7 @@ int aac_src_init(struct aac_dev *dev)
|
||||
dev->a_ops.adapter_sync_cmd = src_sync_cmd;
|
||||
dev->a_ops.adapter_check_health = aac_src_check_health;
|
||||
dev->a_ops.adapter_restart = aac_src_restart_adapter;
|
||||
dev->a_ops.adapter_start = aac_src_start_adapter;
|
||||
|
||||
/*
|
||||
* First clear out all interrupts. Then enable the one's that we
|
||||
@@ -741,7 +750,7 @@ int aac_src_init(struct aac_dev *dev)
|
||||
if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE1)
|
||||
goto error_iounmap;
|
||||
|
||||
dev->msi = aac_msi && !pci_enable_msi(dev->pdev);
|
||||
dev->msi = !pci_enable_msi(dev->pdev);
|
||||
|
||||
dev->aac_msix[0].vector_no = 0;
|
||||
dev->aac_msix[0].dev = dev;
|
||||
@@ -789,9 +798,7 @@ int aac_srcv_init(struct aac_dev *dev)
|
||||
unsigned long status;
|
||||
int restart = 0;
|
||||
int instance = dev->id;
|
||||
int i, j;
|
||||
const char *name = dev->name;
|
||||
int cpu;
|
||||
|
||||
dev->a_ops.adapter_ioremap = aac_srcv_ioremap;
|
||||
dev->a_ops.adapter_comm = aac_src_select_comm;
|
||||
@@ -892,6 +899,7 @@ int aac_srcv_init(struct aac_dev *dev)
|
||||
dev->a_ops.adapter_sync_cmd = src_sync_cmd;
|
||||
dev->a_ops.adapter_check_health = aac_src_check_health;
|
||||
dev->a_ops.adapter_restart = aac_src_restart_adapter;
|
||||
dev->a_ops.adapter_start = aac_src_start_adapter;
|
||||
|
||||
/*
|
||||
* First clear out all interrupts. Then enable the one's that we
|
||||
@@ -908,48 +916,10 @@ int aac_srcv_init(struct aac_dev *dev)
|
||||
goto error_iounmap;
|
||||
if (dev->msi_enabled)
|
||||
aac_src_access_devreg(dev, AAC_ENABLE_MSIX);
|
||||
if (!dev->sync_mode && dev->msi_enabled && dev->max_msix > 1) {
|
||||
cpu = cpumask_first(cpu_online_mask);
|
||||
for (i = 0; i < dev->max_msix; i++) {
|
||||
dev->aac_msix[i].vector_no = i;
|
||||
dev->aac_msix[i].dev = dev;
|
||||
|
||||
if (request_irq(dev->msixentry[i].vector,
|
||||
dev->a_ops.adapter_intr,
|
||||
0,
|
||||
"aacraid",
|
||||
&(dev->aac_msix[i]))) {
|
||||
printk(KERN_ERR "%s%d: Failed to register IRQ for vector %d.\n",
|
||||
name, instance, i);
|
||||
for (j = 0 ; j < i ; j++)
|
||||
free_irq(dev->msixentry[j].vector,
|
||||
&(dev->aac_msix[j]));
|
||||
pci_disable_msix(dev->pdev);
|
||||
goto error_iounmap;
|
||||
}
|
||||
if (irq_set_affinity_hint(
|
||||
dev->msixentry[i].vector,
|
||||
get_cpu_mask(cpu))) {
|
||||
printk(KERN_ERR "%s%d: Failed to set IRQ affinity for cpu %d\n",
|
||||
name, instance, cpu);
|
||||
}
|
||||
cpu = cpumask_next(cpu, cpu_online_mask);
|
||||
}
|
||||
} else {
|
||||
dev->aac_msix[0].vector_no = 0;
|
||||
dev->aac_msix[0].dev = dev;
|
||||
if (aac_acquire_irq(dev))
|
||||
goto error_iounmap;
|
||||
|
||||
if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
|
||||
IRQF_SHARED,
|
||||
"aacraid",
|
||||
&(dev->aac_msix[0])) < 0) {
|
||||
if (dev->msi)
|
||||
pci_disable_msi(dev->pdev);
|
||||
printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
|
||||
name, instance);
|
||||
goto error_iounmap;
|
||||
}
|
||||
}
|
||||
dev->dbg_base = dev->base_start;
|
||||
dev->dbg_base_mapped = dev->base;
|
||||
dev->dbg_size = dev->base_size;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user