RE: [PATCH 1/7] aacraid: AIF support for SES device add/remove
Reviewed-by: Murthy Bhat -Original Message- From: Mahesh Rajashekhara Sent: Wednesday, March 04, 2015 2:08 PM To: jbottom...@parallels.com; linux-scsi@vger.kernel.org Cc: aacr...@pmc-sierra.com; Harry Yang; Achim Leubner; Rajinikanth Pandurangan; Rich Bono; Mahesh Rajashekhara Subject: [PATCH 1/7] aacraid: AIF support for SES device add/remove Add new AIF support for SES device add/remove Signed-off-by: Mahesh Rajashekhara --- drivers/scsi/aacraid/aacraid.h |2 ++ drivers/scsi/aacraid/commsup.c |8 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index eaaf870..284db39 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -1951,6 +1951,8 @@ extern struct aac_common aac_config; #defineAifEnEnclosureManagement 13 /* EM_DRIVE_* */ #defineEM_DRIVE_INSERTION 31 #defineEM_DRIVE_REMOVAL32 +#defineEM_SES_DRIVE_INSERTION 33 +#defineEM_SES_DRIVE_REMOVAL26 #defineAifEnBatteryEvent 14 /* Change in Battery State */ #defineAifEnAddContainer 15 /* A new array was created */ #defineAifEnDeleteContainer16 /* A container was deleted */ diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index cab190a..090ba68 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -1044,6 +1044,8 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) switch (le32_to_cpu(((__le32 *)aifcmd->data)[3])) { case EM_DRIVE_INSERTION: case EM_DRIVE_REMOVAL: + case EM_SES_DRIVE_INSERTION: + case EM_SES_DRIVE_REMOVAL: container = le32_to_cpu( ((__le32 *)aifcmd->data)[2]); if ((container >> 28)) { @@ -1069,8 +1071,10 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) } channel = aac_phys_to_logical(channel); device_config_needed = - (((__le32 *)aifcmd->data)[3] - == cpu_to_le32(EM_DRIVE_INSERTION)) ? + __le32 *)aifcmd->data)[3] + == cpu_to_le32(EM_DRIVE_INSERTION)) || + (((__le32 *)aifcmd->data)[3] + == cpu_to_le32(EM_SES_DRIVE_INSERTION))) ? ADD : DELETE; break; } -- 1.7.7.3 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH 3/7] aacraid: 4KB sector support
Reviewed-by: Murthy Bhat -Original Message- From: Mahesh Rajashekhara Sent: Wednesday, March 04, 2015 2:08 PM To: jbottom...@parallels.com; linux-scsi@vger.kernel.org Cc: aacr...@pmc-sierra.com; Harry Yang; Achim Leubner; Rajinikanth Pandurangan; Rich Bono; Mahesh Rajashekhara Subject: [PATCH 3/7] aacraid: 4KB sector support Add 4KB sector support Signed-off-by: Mahesh Rajashekhara --- drivers/scsi/aacraid/aachba.c | 195 +++- drivers/scsi/aacraid/aacraid.h | 10 ++- 2 files changed, 160 insertions(+), 45 deletions(-) diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index b32e77d..0819644 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -111,6 +111,41 @@ #define BYTE2(x) (unsigned char)((x) >> 16) #define BYTE3(x) (unsigned char)((x) >> 24) +/* MODE_SENSE data format */ +typedef struct { + struct { + u8 data_length; + u8 med_type; + u8 dev_par; + u8 bd_length; + } __attribute__((packed)) hd; + struct { + u8 dens_code; + u8 block_count[3]; + u8 reserved; + u8 block_length[3]; + } __attribute__((packed)) bd; + u8 mpc_buf[3]; +} __attribute__((packed)) aac_modep_data; + +/* MODE_SENSE_10 data format */ +typedef struct { + struct { + u8 data_length[2]; + u8 med_type; + u8 dev_par; + u8 rsrvd[2]; + u8 bd_length[2]; + } __attribute__((packed)) hd; + struct { + u8 dens_code; + u8 block_count[3]; + u8 reserved; + u8 block_length[3]; + } __attribute__((packed)) bd; + u8 mpc_buf[3]; +} __attribute__((packed)) aac_modep10_data; + /*-- * S T R U C T S / T Y P E D E F S **/ @@ -539,6 +574,13 @@ static void _aac_probe_container2(void * context, struct fib * fibptr) if ((le32_to_cpu(dresp->status) == ST_OK) && (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { + if (!(fibptr->dev->supplement_adapter_info.SupportedOptions2 & + AAC_OPTION_VARIABLE_BLOCK_SIZE)) { + dresp->mnt[0].fileinfo.bdevinfo.block_size = 0x200; + fsa_dev_ptr->block_size = 0x200; + } else { + fsa_dev_ptr->block_size = le32_to_cpu(dresp->mnt[0].fileinfo.bdevinfo.block_size); + } fsa_dev_ptr->valid = 1; /* sense_key holds the current state of the spin-up */ if (dresp->mnt[0].state & cpu_to_le32(FSCS_NOT_READY)) @@ -586,7 +628,12 @@ static void _aac_probe_container1(void * context, struct fib * fibptr) dinfo = (struct aac_query_mount *)fib_data(fibptr); - dinfo->command = cpu_to_le32(VM_NameServe64); + if (fibptr->dev->supplement_adapter_info.SupportedOptions2 & + AAC_OPTION_VARIABLE_BLOCK_SIZE) + dinfo->command = cpu_to_le32(VM_NameServeAllBlk); + else + dinfo->command = cpu_to_le32(VM_NameServe64); + dinfo->count = cpu_to_le32(scmd_id(scsicmd)); dinfo->type = cpu_to_le32(FT_FILESYS); @@ -621,7 +668,12 @@ static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(stru dinfo = (struct aac_query_mount *)fib_data(fibptr); - dinfo->command = cpu_to_le32(VM_NameServe); + if (fibptr->dev->supplement_adapter_info.SupportedOptions2 & + AAC_OPTION_VARIABLE_BLOCK_SIZE) + dinfo->command = cpu_to_le32(VM_NameServeAllBlk); + else + dinfo->command = cpu_to_le32(VM_NameServe); + dinfo->count = cpu_to_le32(scmd_id(scsicmd)); dinfo->type = cpu_to_le32(FT_FILESYS); scsicmd->SCp.ptr = (char *)callback; @@ -982,7 +1034,7 @@ static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3 memset(readcmd2, 0, sizeof(struct aac_raw_io2)); readcmd2->blockLow = cpu_to_le32((u32)(lba&0x)); readcmd2->blockHigh = cpu_to_le32((u32)((lba&0xLL)>>32)); - readcmd2->byteCount = cpu_to_le32(count<<9); + readcmd2->byteCount = cpu_to_le32(count * dev->fsa_dev[scmd_id(cmd)].block_size); readcmd2->cid = cpu_to_le16(scmd_id(cmd));
RE: [PATCH 7/7] aacraid: AIF raw device remove support
Reviewed-by: Murthy Bhat -Original Message- From: Mahesh Rajashekhara Sent: Wednesday, March 04, 2015 2:09 PM To: jbottom...@parallels.com; linux-scsi@vger.kernel.org Cc: aacr...@pmc-sierra.com; Harry Yang; Achim Leubner; Rajinikanth Pandurangan; Rich Bono; Mahesh Rajashekhara Subject: [PATCH 7/7] aacraid: AIF raw device remove support Add AIF raw device remove support Signed-off-by: Mahesh Rajashekhara --- drivers/scsi/aacraid/aacraid.h |3 +++ drivers/scsi/aacraid/commsup.c | 32 2 files changed, 35 insertions(+), 0 deletions(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 74a0440..5aaa9a6 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -2061,6 +2061,9 @@ extern struct aac_common aac_config; /* PMC NEW COMM: Request the event data */ #defineAifReqEvent 200 +/* RAW device deleted */ +#defineAifRawDeviceRemove 203 + /* * Adapter Initiated FIB command structures. Start with the adapter * initiated FIBs that really come from the adapter, and get responded diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 0555023..8bb9ee4 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -884,6 +884,38 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) switch (le32_to_cpu(aifcmd->command)) { case AifCmdDriverNotify: switch (le32_to_cpu(((__le32 *)aifcmd->data)[0])) { + case AifRawDeviceRemove: + container = le32_to_cpu(((__le32 *)aifcmd->data)[1]); + if ((container >> 28)) { + container = (u32)-1; + break; + } + channel = (container >> 24) & 0xF; + if (channel >= dev->maximum_num_channels) { + container = (u32)-1; + break; + } + id = container & 0x; + if (id >= dev->maximum_num_physicals) { + container = (u32)-1; + break; + } + lun = (container >> 16) & 0xFF; + container = (u32)-1; + channel = aac_phys_to_logical(channel); + device_config_needed = + (((__le32 *)aifcmd->data)[0] == + cpu_to_le32(AifRawDeviceRemove)) ? DELETE : ADD; + + if (device_config_needed == ADD) { + device = scsi_device_lookup(dev->scsi_host_ptr, channel, id, lun); + if (device) { + scsi_remove_device(device); + scsi_device_put(device); + } + } + break; + /* * Morph or Expand complete */ -- 1.7.7.3 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH 2/7] aacraid: IOCTL pass-through command fix
Reviewed-by: Murthy Bhat -Original Message- From: Mahesh Rajashekhara Sent: Wednesday, March 04, 2015 2:08 PM To: jbottom...@parallels.com; linux-scsi@vger.kernel.org Cc: aacr...@pmc-sierra.com; Harry Yang; Achim Leubner; Rajinikanth Pandurangan; Rich Bono; Mahesh Rajashekhara Subject: [PATCH 2/7] aacraid: IOCTL pass-through command fix The Linux aacriad driver fails to detect the case of SG list count=0 on IOCTL pass-through command and cause intermittent fault. The result is the Linux aacriad driver send down IOCTL pass-through command with one not initialized SG list to firmware when receiving SG list count =0 on pass-through command. Signed-off-by: Mahesh Rajashekhara --- drivers/scsi/aacraid/commctrl.c | 10 -- 1 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index fbcd48d..54195a1 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -689,7 +689,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) kfree (usg); } srbcmd->count = cpu_to_le32(byte_count); - psg->count = cpu_to_le32(sg_indx+1); + if (user_srbcmd->sg.count) + psg->count = cpu_to_le32(sg_indx+1); + else + psg->count = 0; status = aac_fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL); } else { struct user_sgmap* upsg = &user_srbcmd->sg; @@ -775,7 +778,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) } } srbcmd->count = cpu_to_le32(byte_count); - psg->count = cpu_to_le32(sg_indx+1); + if (user_srbcmd->sg.count) + psg->count = cpu_to_le32(sg_indx+1); + else + psg->count = 0; status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL); } if (status == -ERESTARTSYS) { -- 1.7.7.3 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH 5/7] aacraid: vpd page code 0x83 support
Reviewed-by: Murthy Bhat -Original Message- From: Mahesh Rajashekhara Sent: Wednesday, March 04, 2015 2:09 PM To: jbottom...@parallels.com; linux-scsi@vger.kernel.org Cc: aacr...@pmc-sierra.com; Harry Yang; Achim Leubner; Rajinikanth Pandurangan; Rich Bono; Mahesh Rajashekhara Subject: [PATCH 5/7] aacraid: vpd page code 0x83 support Add vpd page code 0x83 support Signed-off-by: Mahesh Rajashekhara --- drivers/scsi/aacraid/aachba.c | 154 --- drivers/scsi/aacraid/aacraid.h |4 + drivers/scsi/aacraid/comminit.c |8 ++- drivers/scsi/aacraid/commsup.c | 12 +--- drivers/scsi/aacraid/linit.c| 20 + drivers/scsi/aacraid/src.c | 34 +++-- 6 files changed, 185 insertions(+), 47 deletions(-) diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index eb524e6..3e4e0c8 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -163,6 +163,45 @@ struct inquiry_data { u8 inqd_prl[4]; /* Product Revision Level */ }; +/* Added for VPD 0x83 */ +typedef struct { + u8 CodeSet:4; /* VPD_CODE_SET */ + u8 Reserved:4; + u8 IdentifierType:4;/* VPD_IDENTIFIER_TYPE */ + u8 Reserved2:4; + u8 Reserved3; + u8 IdentifierLength; + u8 VendId[8]; + u8 ProductId[16]; + u8 SerialNumber[8]; /* SN in ASCII */ +} TVPD_ID_Descriptor_Type_1; + +typedef struct { + u8 CodeSet:4; /* VPD_CODE_SET */ + u8 Reserved:4; + u8 IdentifierType:4;/* VPD_IDENTIFIER_TYPE */ + u8 Reserved2:4; + u8 Reserved3; + u8 IdentifierLength; + struct TEU64Id { + u32 Serial; +/* The serial number supposed to be 40 bits, + * bit we only support 32, so make the last byte zero. */ + u8 Reserved; + u8 VendId[3]; + } EU64Id; +} TVPD_ID_Descriptor_Type_2; + +typedef struct { + u8 DeviceType:5; + u8 DeviceTypeQualifier:3; + u8 PageCode; + u8 Reserved; + u8 PageLength; + TVPD_ID_Descriptor_Type_1 IdDescriptorType1; + TVPD_ID_Descriptor_Type_2 IdDescriptorType2; +} TVPD_Page83; + /* * M O D U L E G L O B A L S */ @@ -420,6 +459,9 @@ int aac_get_containers(struct aac_dev *dev) if (status >= 0) { dresp = (struct aac_get_container_count_resp *)fib_data(fibptr); maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries); + if (fibptr->dev->supplement_adapter_info.SupportedOptions2 & + AAC_OPTION_SUPPORTED_240_VOLUMES) + maximum_num_containers = le32_to_cpu(dresp->MaxSimpleVolumes); aac_fib_complete(fibptr); } /* FIB should be freed only after getting the response from the F/W */ @@ -889,14 +931,81 @@ static void get_container_serial_callback(void *context, struct fib * fibptr) get_serial_reply = (struct aac_get_serial_resp *) fib_data(fibptr); /* Failure is irrelevant, using default value instead */ if (le32_to_cpu(get_serial_reply->status) == CT_OK) { - char sp[13]; - /* EVPD bit set */ - sp[0] = INQD_PDT_DA; - sp[1] = scsicmd->cmnd[2]; - sp[2] = 0; - sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X", - le32_to_cpu(get_serial_reply->uid)); - scsi_sg_copy_from_buffer(scsicmd, sp, sizeof(sp)); + /*Check to see if it's for VPD 0x83 or 0x80 */ + if (scsicmd->cmnd[2] == 0x83) { + /* vpd page 0x83 - Device Identification Page */ + int i; + TVPD_Page83 VPDPage83Data; + + memset(((u8 *)&VPDPage83Data), 0, + sizeof(VPDPage83Data)); + + /* DIRECT_ACCESS_DEVIC */ + VPDPage83Data.DeviceType = 0; + /* DEVICE_CONNECTED */ + VPDPage83Data.DeviceTypeQualifier = 0; + /* VPD_DEVICE_IDENTIFIERS */ + VPDPage83Data.PageCode = 0x83; + VPDPage83Data.Reserved = 0; + VPDPage83Data.PageLength = sizeof(VPDPage83Data.IdDescriptorType1) + + sizeof(VPDPage83Data.IdDescriptorType2); + + /* T10 Vendor Identifier Field Format */ + /* VpdCodeSetAscii */ + VPDPage83Data.IdDescriptorType1.CodeSet = 2; + /* VpdIdentifierTypeVendorId */ + VPDPage83Data.IdDescriptorType1.IdentifierType = 1; + VPDPage83Data.IdDescriptorType1.IdentifierLength = sizeof(VPDPage83Data.IdDescriptorType1) - 4; + + /* "ADAPTEC " for adaptec */ + memcpy(VPDPage83Data.IdDesc
RE: [PATCH 4/7] aacraid: MSI-x support
Reviewed-by: Murthy Bhat -Original Message- From: Mahesh Rajashekhara Sent: Wednesday, March 04, 2015 2:09 PM To: jbottom...@parallels.com; linux-scsi@vger.kernel.org Cc: aacr...@pmc-sierra.com; Harry Yang; Achim Leubner; Rajinikanth Pandurangan; Rich Bono; Mahesh Rajashekhara Subject: [PATCH 4/7] aacraid: MSI-x support Add MSI-x interrupt mode support. Signed-off-by: Mahesh Rajashekhara --- drivers/scsi/aacraid/aachba.c |6 +- drivers/scsi/aacraid/aacraid.h | 79 - drivers/scsi/aacraid/comminit.c | 86 +- drivers/scsi/aacraid/commsup.c | 19 ++- drivers/scsi/aacraid/dpcsup.c |9 +- drivers/scsi/aacraid/linit.c| 18 ++- drivers/scsi/aacraid/src.c | 365 +-- 7 files changed, 473 insertions(+), 109 deletions(-) diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 0819644..eb524e6 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -473,7 +473,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr) if ((le32_to_cpu(get_name_reply->status) == CT_OK) && (get_name_reply->data[0] != '\0')) { char *sp = get_name_reply->data; - sp[sizeof(((struct aac_get_name_resp *)NULL)->data)-1] = '\0'; + sp[sizeof(((struct aac_get_name_resp *)NULL)->data)] = '\0'; while (*sp == ' ') ++sp; if (*sp) { @@ -613,7 +613,9 @@ static void _aac_probe_container1(void * context, struct fib * fibptr) int status; dresp = (struct aac_mount *) fib_data(fibptr); - dresp->mnt[0].capacityhigh = 0; + if (!(fibptr->dev->supplement_adapter_info.SupportedOptions2 & + AAC_OPTION_VARIABLE_BLOCK_SIZE)) + dresp->mnt[0].capacityhigh = 0; if ((le32_to_cpu(dresp->status) != ST_OK) || (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) { _aac_probe_container2(context, fibptr); diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 93579f3..c162a65 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -6,11 +6,61 @@ #define nblank(x) _nblank(x)[0] #include +#include /*-- * D E F I N E S **/ +#define AAC_MAX_MSIX 32 /* vectors */ +#define AAC_PCI_MSI_ENABLE 0x8000 + +enum { + AAC_ENABLE_INTERRUPT= 0x0, + AAC_DISABLE_INTERRUPT, + AAC_ENABLE_MSIX, + AAC_DISABLE_MSIX, + AAC_CLEAR_AIF_BIT, + AAC_CLEAR_SYNC_BIT, + AAC_ENABLE_INTX +}; + +#define AAC_INT_MODE_INTX (1<<0) +#define AAC_INT_MODE_MSI (1<<1) +#define AAC_INT_MODE_AIF (1<<2) +#define AAC_INT_MODE_SYNC (1<<3) + +#define AAC_INT_ENABLE_TYPE1_INTX 0xfffb +#define AAC_INT_ENABLE_TYPE1_MSIX 0xfffa +#define AAC_INT_DISABLE_ALL0x + +/* Bit definitions in IOA->Host Interrupt Register */ +#define PMC_TRANSITION_TO_OPERATIONAL (0x8000 >> 0) +#define PMC_IOARCB_TRANSFER_FAILED (0x8000 >> 3) +#define PMC_IOA_UNIT_CHECK (0x8000 >> 4) +#define PMC_NO_HOST_RRQ_FOR_CMD_RESPONSE (0x8000 >> 5) +#define PMC_CRITICAL_IOA_OP_IN_PROGRESS(0x8000 >> 6) +#define PMC_IOARRIN_LOST (0x8000 >> 27) +#define PMC_SYSTEM_BUS_MMIO_ERROR (0x8000 >> 28) +#define PMC_IOA_PROCESSOR_IN_ERROR_STATE (0x8000 >> 29) +#define PMC_HOST_RRQ_VALID (0x8000 >> 30) +#define PMC_OPERATIONAL_STATUS (0x8000 >> 0) +#define PMC_ALLOW_MSIX_VECTOR0 (0x8000 >> 31) + +#define PMC_IOA_ERROR_INTERRUPTS (PMC_IOARCB_TRANSFER_FAILED | \ +PMC_IOA_UNIT_CHECK | \ +PMC_NO_HOST_RRQ_FOR_CMD_RESPONSE | \ +PMC_IOARRIN_LOST | \ +PMC_SYSTEM_BUS_MMIO_ERROR | \ +PMC_IOA_PROCESSOR_IN_ERROR_STATE) + +#define PMC_ALL_INTERRUPT_BITS (PMC_IOA_ERROR_INTERRUPTS | \ +PMC_HOST_RRQ_VALID | \ +PMC_TRANSITION_TO_OPERATIONAL | \ +PMC_ALLOW_MSIX_VECTOR0) +#definePMC_GLOBAL_INT_BIT2 0x0004 +#definePMC_GLOBAL_INT_BIT0 0x0001 + #ifndef AAC_DRIVER_BUILD # define AAC_DRIVER_BUILD 30300 # define AAC_DRIVER_BRANCH "-ms" @@ -36,6 +86,7 @@ #define CONTAINER_TO_ID(cont) (cont) #define CONTAINER_TO_LUN(cont) (0) +#define PMC_DEVICE_S6 0x28b #define PMC_DEVICE_S7 0x28c #define PMC_DEVICE_S8 0x28d #define PMC_DEVICE_S9
RE: [PATCH 6/7] aacraid: performance improvement changes
Reviewed-by: Murthy Bhat -Original Message- From: Mahesh Rajashekhara Sent: Wednesday, March 04, 2015 2:09 PM To: jbottom...@parallels.com; linux-scsi@vger.kernel.org Cc: aacr...@pmc-sierra.com; Harry Yang; Achim Leubner; Rajinikanth Pandurangan; Rich Bono; Mahesh Rajashekhara Subject: [PATCH 6/7] aacraid: performance improvement changes Add performance improvement changes. Signed-off-by: Mahesh Rajashekhara --- drivers/scsi/aacraid/aacraid.h |6 +++--- drivers/scsi/aacraid/comminit.c | 12 +++- drivers/scsi/aacraid/commsup.c |7 ++- drivers/scsi/aacraid/dpcsup.c |4 ++-- drivers/scsi/aacraid/linit.c| 10 -- drivers/scsi/aacraid/rx.c | 14 +++--- drivers/scsi/aacraid/src.c |5 + 7 files changed, 26 insertions(+), 32 deletions(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index a37762e..74a0440 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -12,7 +12,7 @@ * D E F I N E S **/ -#define AAC_MAX_MSIX 32 /* vectors */ +#define AAC_MAX_MSIX 8 /* vectors */ #define AAC_PCI_MSI_ENABLE 0x8000 enum { @@ -62,7 +62,7 @@ enum { #definePMC_GLOBAL_INT_BIT0 0x0001 #ifndef AAC_DRIVER_BUILD -# define AAC_DRIVER_BUILD 30300 +# define AAC_DRIVER_BUILD 40709 # define AAC_DRIVER_BRANCH "-ms" #endif #define MAXIMUM_NUM_CONTAINERS 32 @@ -633,7 +633,7 @@ struct aac_queue { spinlock_t lockdata; /* Actual lock (used only on one side of the lock) */ struct list_headcmdq; /* A queue of FIBs which need to be prcessed by the FS thread. This is */ /* only valid for command queues which receive entries from the adapter. */ - u32 numpending; /* Number of entries on outstanding queue. */ + atomic_tnumpending; /* Number of entries on outstanding queue. */ struct aac_dev *dev;/* Back pointer to adapter structure */ }; diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index c3e13ae..c16043e 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -181,7 +181,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem, int qsize) { - q->numpending = 0; + atomic_set(&q->numpending, 0); q->dev = dev; init_waitqueue_head(&q->cmdready); INIT_LIST_HEAD(&q->cmdq); @@ -510,6 +510,7 @@ static void aac_define_int_mode(struct aac_dev *dev) { int i, msi_count; + int cpu; msi_count = i = 0; /* max. vectors from GET_COMM_PREFERRED_SETTINGS */ @@ -571,6 +572,15 @@ static void aac_define_int_mode(struct aac_dev *dev) else { if (dev->max_msix > msi_count) dev->max_msix = msi_count; + + /* Added to set IRQ affinity */ + cpu = cpumask_first(cpu_online_mask); + cpu = cpumask_next(cpu, cpu_online_mask); + + for (i = 0; i < dev->max_msix; i++) { + irq_set_affinity_hint(dev->msixentry[i].vector, get_cpu_mask(cpu)); + cpu = cpumask_next(cpu, cpu_online_mask); + } } dev->vector_cap = (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) / msi_count; } diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 2bed445..0555023 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -318,7 +318,7 @@ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entr /* Queue is full */ if ((*index + 1) == le32_to_cpu(*(q->headers.consumer))) { printk(KERN_WARNING "Queue %d full, %u outstanding.\n", - qid, q->numpending); + qid, atomic_read(&q->numpending)); return 0; } else { *entry = q->base + *index; @@ -411,7 +411,6 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, struct aac_dev * dev = fibptr->dev; struct hw_fib * hw_fib = fibptr->hw_fib_va; unsigned long flags = 0; - unsigned long qflags; unsigned long mflags = 0; unsigned long sflags = 0; @@ -565,9 +564,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, int blink; if (time_is_before_eq_jiffies(timeout)) { struct aac_queue * q = &dev->queues->queue[AdapNormCmdQueue]; -
RE: [PATCH 3/7] aacraid: 4KB sector support
Reviewed-by: Achim Leubner -Original Message- From: Mahesh Rajashekhara Sent: Wednesday, March 4, 2015 9:38 AM To: jbottom...@parallels.com; linux-scsi@vger.kernel.org Cc: aacr...@pmc-sierra.com; Harry Yang; Achim Leubner; Rajinikanth Pandurangan; Rich Bono; Mahesh Rajashekhara Subject: [PATCH 3/7] aacraid: 4KB sector support Add 4KB sector support Signed-off-by: Mahesh Rajashekhara --- drivers/scsi/aacraid/aachba.c | 195 +++- drivers/scsi/aacraid/aacraid.h | 10 ++- 2 files changed, 160 insertions(+), 45 deletions(-) diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index b32e77d..0819644 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -111,6 +111,41 @@ #define BYTE2(x) (unsigned char)((x) >> 16) #define BYTE3(x) (unsigned char)((x) >> 24) +/* MODE_SENSE data format */ +typedef struct { + struct { + u8 data_length; + u8 med_type; + u8 dev_par; + u8 bd_length; + } __attribute__((packed)) hd; + struct { + u8 dens_code; + u8 block_count[3]; + u8 reserved; + u8 block_length[3]; + } __attribute__((packed)) bd; + u8 mpc_buf[3]; +} __attribute__((packed)) aac_modep_data; + +/* MODE_SENSE_10 data format */ +typedef struct { + struct { + u8 data_length[2]; + u8 med_type; + u8 dev_par; + u8 rsrvd[2]; + u8 bd_length[2]; + } __attribute__((packed)) hd; + struct { + u8 dens_code; + u8 block_count[3]; + u8 reserved; + u8 block_length[3]; + } __attribute__((packed)) bd; + u8 mpc_buf[3]; +} __attribute__((packed)) aac_modep10_data; + /*-- * S T R U C T S / T Y P E D E F S **/ @@ -539,6 +574,13 @@ static void _aac_probe_container2(void * context, struct fib * fibptr) if ((le32_to_cpu(dresp->status) == ST_OK) && (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { + if (!(fibptr->dev->supplement_adapter_info.SupportedOptions2 & + AAC_OPTION_VARIABLE_BLOCK_SIZE)) { + dresp->mnt[0].fileinfo.bdevinfo.block_size = 0x200; + fsa_dev_ptr->block_size = 0x200; + } else { + fsa_dev_ptr->block_size = le32_to_cpu(dresp->mnt[0].fileinfo.bdevinfo.block_size); + } fsa_dev_ptr->valid = 1; /* sense_key holds the current state of the spin-up */ if (dresp->mnt[0].state & cpu_to_le32(FSCS_NOT_READY)) @@ -586,7 +628,12 @@ static void _aac_probe_container1(void * context, struct fib * fibptr) dinfo = (struct aac_query_mount *)fib_data(fibptr); - dinfo->command = cpu_to_le32(VM_NameServe64); + if (fibptr->dev->supplement_adapter_info.SupportedOptions2 & + AAC_OPTION_VARIABLE_BLOCK_SIZE) + dinfo->command = cpu_to_le32(VM_NameServeAllBlk); + else + dinfo->command = cpu_to_le32(VM_NameServe64); + dinfo->count = cpu_to_le32(scmd_id(scsicmd)); dinfo->type = cpu_to_le32(FT_FILESYS); @@ -621,7 +668,12 @@ static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(stru dinfo = (struct aac_query_mount *)fib_data(fibptr); - dinfo->command = cpu_to_le32(VM_NameServe); + if (fibptr->dev->supplement_adapter_info.SupportedOptions2 & + AAC_OPTION_VARIABLE_BLOCK_SIZE) + dinfo->command = cpu_to_le32(VM_NameServeAllBlk); + else + dinfo->command = cpu_to_le32(VM_NameServe); + dinfo->count = cpu_to_le32(scmd_id(scsicmd)); dinfo->type = cpu_to_le32(FT_FILESYS); scsicmd->SCp.ptr = (char *)callback; @@ -982,7 +1034,7 @@ static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3 memset(readcmd2, 0, sizeof(struct aac_raw_io2)); readcmd2->blockLow = cpu_to_le32((u32)(lba&0x)); readcmd2->blockHigh = cpu_to_le32((u32)((lba&0xLL)>>32)); - readcmd2->byteCount = cpu_to_le32(count<<9); + readcmd2->byteCount = cpu_to_le32(count * +dev->fsa_dev[scmd_id(cmd)].block_size); readcmd2->cid = cpu_to_le16(scmd_id(cmd));
RE: [PATCH 6/7] aacraid: performance improvement changes
Reviewed-by: Achim Leubner -Original Message- From: Mahesh Rajashekhara Sent: Wednesday, March 4, 2015 9:39 AM To: jbottom...@parallels.com; linux-scsi@vger.kernel.org Cc: aacr...@pmc-sierra.com; Harry Yang; Achim Leubner; Rajinikanth Pandurangan; Rich Bono; Mahesh Rajashekhara Subject: [PATCH 6/7] aacraid: performance improvement changes Add performance improvement changes. Signed-off-by: Mahesh Rajashekhara --- drivers/scsi/aacraid/aacraid.h |6 +++--- drivers/scsi/aacraid/comminit.c | 12 +++- drivers/scsi/aacraid/commsup.c |7 ++- drivers/scsi/aacraid/dpcsup.c |4 ++-- drivers/scsi/aacraid/linit.c| 10 -- drivers/scsi/aacraid/rx.c | 14 +++--- drivers/scsi/aacraid/src.c |5 + 7 files changed, 26 insertions(+), 32 deletions(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index a37762e..74a0440 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -12,7 +12,7 @@ * D E F I N E S **/ -#define AAC_MAX_MSIX 32 /* vectors */ +#define AAC_MAX_MSIX 8 /* vectors */ #define AAC_PCI_MSI_ENABLE 0x8000 enum { @@ -62,7 +62,7 @@ enum { #definePMC_GLOBAL_INT_BIT0 0x0001 #ifndef AAC_DRIVER_BUILD -# define AAC_DRIVER_BUILD 30300 +# define AAC_DRIVER_BUILD 40709 # define AAC_DRIVER_BRANCH "-ms" #endif #define MAXIMUM_NUM_CONTAINERS 32 @@ -633,7 +633,7 @@ struct aac_queue { spinlock_t lockdata; /* Actual lock (used only on one side of the lock) */ struct list_headcmdq; /* A queue of FIBs which need to be prcessed by the FS thread. This is */ /* only valid for command queues which receive entries from the adapter. */ - u32 numpending; /* Number of entries on outstanding queue. */ + atomic_tnumpending; /* Number of entries on outstanding queue. */ struct aac_dev *dev;/* Back pointer to adapter structure */ }; diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index c3e13ae..c16043e 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -181,7 +181,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem, int qsize) { - q->numpending = 0; + atomic_set(&q->numpending, 0); q->dev = dev; init_waitqueue_head(&q->cmdready); INIT_LIST_HEAD(&q->cmdq); @@ -510,6 +510,7 @@ static void aac_define_int_mode(struct aac_dev *dev) { int i, msi_count; + int cpu; msi_count = i = 0; /* max. vectors from GET_COMM_PREFERRED_SETTINGS */ @@ -571,6 +572,15 @@ static void aac_define_int_mode(struct aac_dev *dev) else { if (dev->max_msix > msi_count) dev->max_msix = msi_count; + + /* Added to set IRQ affinity */ + cpu = cpumask_first(cpu_online_mask); + cpu = cpumask_next(cpu, cpu_online_mask); + + for (i = 0; i < dev->max_msix; i++) { + irq_set_affinity_hint(dev->msixentry[i].vector, get_cpu_mask(cpu)); + cpu = cpumask_next(cpu, cpu_online_mask); + } } dev->vector_cap = (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) / msi_count; } diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 2bed445..0555023 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -318,7 +318,7 @@ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entr /* Queue is full */ if ((*index + 1) == le32_to_cpu(*(q->headers.consumer))) { printk(KERN_WARNING "Queue %d full, %u outstanding.\n", - qid, q->numpending); + qid, atomic_read(&q->numpending)); return 0; } else { *entry = q->base + *index; @@ -411,7 +411,6 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, struct aac_dev * dev = fibptr->dev; struct hw_fib * hw_fib = fibptr->hw_fib_va; unsigned long flags = 0; - unsigned long qflags; unsigned long mflags = 0; unsigned long sflags = 0; @@ -565,9 +564,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, int blink; if (time_is_before_eq_jiffies(timeout)) { struct aac_queue * q = &dev->queues->queue[AdapNormCmdQueue]; -
RE: [PATCH 7/7] aacraid: AIF raw device remove support
Reviewed-by: Achim Leubner -Original Message- From: Mahesh Rajashekhara Sent: Wednesday, March 4, 2015 9:39 AM To: jbottom...@parallels.com; linux-scsi@vger.kernel.org Cc: aacr...@pmc-sierra.com; Harry Yang; Achim Leubner; Rajinikanth Pandurangan; Rich Bono; Mahesh Rajashekhara Subject: [PATCH 7/7] aacraid: AIF raw device remove support Add AIF raw device remove support Signed-off-by: Mahesh Rajashekhara --- drivers/scsi/aacraid/aacraid.h |3 +++ drivers/scsi/aacraid/commsup.c | 32 2 files changed, 35 insertions(+), 0 deletions(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 74a0440..5aaa9a6 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -2061,6 +2061,9 @@ extern struct aac_common aac_config; /* PMC NEW COMM: Request the event data */ #defineAifReqEvent 200 +/* RAW device deleted */ +#defineAifRawDeviceRemove 203 + /* * Adapter Initiated FIB command structures. Start with the adapter * initiated FIBs that really come from the adapter, and get responded diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 0555023..8bb9ee4 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -884,6 +884,38 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) switch (le32_to_cpu(aifcmd->command)) { case AifCmdDriverNotify: switch (le32_to_cpu(((__le32 *)aifcmd->data)[0])) { + case AifRawDeviceRemove: + container = le32_to_cpu(((__le32 *)aifcmd->data)[1]); + if ((container >> 28)) { + container = (u32)-1; + break; + } + channel = (container >> 24) & 0xF; + if (channel >= dev->maximum_num_channels) { + container = (u32)-1; + break; + } + id = container & 0x; + if (id >= dev->maximum_num_physicals) { + container = (u32)-1; + break; + } + lun = (container >> 16) & 0xFF; + container = (u32)-1; + channel = aac_phys_to_logical(channel); + device_config_needed = + (((__le32 *)aifcmd->data)[0] == + cpu_to_le32(AifRawDeviceRemove)) ? DELETE : ADD; + + if (device_config_needed == ADD) { + device = scsi_device_lookup(dev->scsi_host_ptr, channel, id, lun); + if (device) { + scsi_remove_device(device); + scsi_device_put(device); + } + } + break; + /* * Morph or Expand complete */ -- 1.7.7.3 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH 1/7] aacraid: AIF support for SES device add/remove
Reviewed-by: Achim Leubner -Original Message- From: Mahesh Rajashekhara Sent: Wednesday, March 4, 2015 9:38 AM To: jbottom...@parallels.com; linux-scsi@vger.kernel.org Cc: aacr...@pmc-sierra.com; Harry Yang; Achim Leubner; Rajinikanth Pandurangan; Rich Bono; Mahesh Rajashekhara Subject: [PATCH 1/7] aacraid: AIF support for SES device add/remove Add new AIF support for SES device add/remove Signed-off-by: Mahesh Rajashekhara --- drivers/scsi/aacraid/aacraid.h |2 ++ drivers/scsi/aacraid/commsup.c |8 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index eaaf870..284db39 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -1951,6 +1951,8 @@ extern struct aac_common aac_config; #defineAifEnEnclosureManagement 13 /* EM_DRIVE_* */ #defineEM_DRIVE_INSERTION 31 #defineEM_DRIVE_REMOVAL32 +#defineEM_SES_DRIVE_INSERTION 33 +#defineEM_SES_DRIVE_REMOVAL26 #defineAifEnBatteryEvent 14 /* Change in Battery State */ #defineAifEnAddContainer 15 /* A new array was created */ #defineAifEnDeleteContainer16 /* A container was deleted */ diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index cab190a..090ba68 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -1044,6 +1044,8 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) switch (le32_to_cpu(((__le32 *)aifcmd->data)[3])) { case EM_DRIVE_INSERTION: case EM_DRIVE_REMOVAL: + case EM_SES_DRIVE_INSERTION: + case EM_SES_DRIVE_REMOVAL: container = le32_to_cpu( ((__le32 *)aifcmd->data)[2]); if ((container >> 28)) { @@ -1069,8 +1071,10 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) } channel = aac_phys_to_logical(channel); device_config_needed = - (((__le32 *)aifcmd->data)[3] - == cpu_to_le32(EM_DRIVE_INSERTION)) ? + __le32 *)aifcmd->data)[3] + == cpu_to_le32(EM_DRIVE_INSERTION)) || + (((__le32 *)aifcmd->data)[3] + == cpu_to_le32(EM_SES_DRIVE_INSERTION))) ? ADD : DELETE; break; } -- 1.7.7.3 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH 2/7] aacraid: IOCTL pass-through command fix
Reviewed-by: Achim Leubner -Original Message- From: Mahesh Rajashekhara Sent: Wednesday, March 4, 2015 9:38 AM To: jbottom...@parallels.com; linux-scsi@vger.kernel.org Cc: aacr...@pmc-sierra.com; Harry Yang; Achim Leubner; Rajinikanth Pandurangan; Rich Bono; Mahesh Rajashekhara Subject: [PATCH 2/7] aacraid: IOCTL pass-through command fix The Linux aacriad driver fails to detect the case of SG list count=0 on IOCTL pass-through command and cause intermittent fault. The result is the Linux aacriad driver send down IOCTL pass-through command with one not initialized SG list to firmware when receiving SG list count =0 on pass-through command. Signed-off-by: Mahesh Rajashekhara --- drivers/scsi/aacraid/commctrl.c | 10 -- 1 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index fbcd48d..54195a1 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -689,7 +689,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) kfree (usg); } srbcmd->count = cpu_to_le32(byte_count); - psg->count = cpu_to_le32(sg_indx+1); + if (user_srbcmd->sg.count) + psg->count = cpu_to_le32(sg_indx+1); + else + psg->count = 0; status = aac_fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL); } else { struct user_sgmap* upsg = &user_srbcmd->sg; @@ -775,7 +778,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) } } srbcmd->count = cpu_to_le32(byte_count); - psg->count = cpu_to_le32(sg_indx+1); + if (user_srbcmd->sg.count) + psg->count = cpu_to_le32(sg_indx+1); + else + psg->count = 0; status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL); } if (status == -ERESTARTSYS) { -- 1.7.7.3 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH 5/7] aacraid: vpd page code 0x83 support
Reviewed-by: Achim Leubner -Original Message- From: Mahesh Rajashekhara Sent: Wednesday, March 4, 2015 9:39 AM To: jbottom...@parallels.com; linux-scsi@vger.kernel.org Cc: aacr...@pmc-sierra.com; Harry Yang; Achim Leubner; Rajinikanth Pandurangan; Rich Bono; Mahesh Rajashekhara Subject: [PATCH 5/7] aacraid: vpd page code 0x83 support Add vpd page code 0x83 support Signed-off-by: Mahesh Rajashekhara --- drivers/scsi/aacraid/aachba.c | 154 --- drivers/scsi/aacraid/aacraid.h |4 + drivers/scsi/aacraid/comminit.c |8 ++- drivers/scsi/aacraid/commsup.c | 12 +--- drivers/scsi/aacraid/linit.c| 20 + drivers/scsi/aacraid/src.c | 34 +++-- 6 files changed, 185 insertions(+), 47 deletions(-) diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index eb524e6..3e4e0c8 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -163,6 +163,45 @@ struct inquiry_data { u8 inqd_prl[4]; /* Product Revision Level */ }; +/* Added for VPD 0x83 */ +typedef struct { + u8 CodeSet:4; /* VPD_CODE_SET */ + u8 Reserved:4; + u8 IdentifierType:4;/* VPD_IDENTIFIER_TYPE */ + u8 Reserved2:4; + u8 Reserved3; + u8 IdentifierLength; + u8 VendId[8]; + u8 ProductId[16]; + u8 SerialNumber[8]; /* SN in ASCII */ +} TVPD_ID_Descriptor_Type_1; + +typedef struct { + u8 CodeSet:4; /* VPD_CODE_SET */ + u8 Reserved:4; + u8 IdentifierType:4;/* VPD_IDENTIFIER_TYPE */ + u8 Reserved2:4; + u8 Reserved3; + u8 IdentifierLength; + struct TEU64Id { + u32 Serial; +/* The serial number supposed to be 40 bits, + * bit we only support 32, so make the last byte zero. */ + u8 Reserved; + u8 VendId[3]; + } EU64Id; +} TVPD_ID_Descriptor_Type_2; + +typedef struct { + u8 DeviceType:5; + u8 DeviceTypeQualifier:3; + u8 PageCode; + u8 Reserved; + u8 PageLength; + TVPD_ID_Descriptor_Type_1 IdDescriptorType1; + TVPD_ID_Descriptor_Type_2 IdDescriptorType2; } TVPD_Page83; + /* * M O D U L E G L O B A L S */ @@ -420,6 +459,9 @@ int aac_get_containers(struct aac_dev *dev) if (status >= 0) { dresp = (struct aac_get_container_count_resp *)fib_data(fibptr); maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries); + if (fibptr->dev->supplement_adapter_info.SupportedOptions2 & + AAC_OPTION_SUPPORTED_240_VOLUMES) + maximum_num_containers = le32_to_cpu(dresp->MaxSimpleVolumes); aac_fib_complete(fibptr); } /* FIB should be freed only after getting the response from the F/W */ @@ -889,14 +931,81 @@ static void get_container_serial_callback(void *context, struct fib * fibptr) get_serial_reply = (struct aac_get_serial_resp *) fib_data(fibptr); /* Failure is irrelevant, using default value instead */ if (le32_to_cpu(get_serial_reply->status) == CT_OK) { - char sp[13]; - /* EVPD bit set */ - sp[0] = INQD_PDT_DA; - sp[1] = scsicmd->cmnd[2]; - sp[2] = 0; - sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X", - le32_to_cpu(get_serial_reply->uid)); - scsi_sg_copy_from_buffer(scsicmd, sp, sizeof(sp)); + /*Check to see if it's for VPD 0x83 or 0x80 */ + if (scsicmd->cmnd[2] == 0x83) { + /* vpd page 0x83 - Device Identification Page */ + int i; + TVPD_Page83 VPDPage83Data; + + memset(((u8 *)&VPDPage83Data), 0, + sizeof(VPDPage83Data)); + + /* DIRECT_ACCESS_DEVIC */ + VPDPage83Data.DeviceType = 0; + /* DEVICE_CONNECTED */ + VPDPage83Data.DeviceTypeQualifier = 0; + /* VPD_DEVICE_IDENTIFIERS */ + VPDPage83Data.PageCode = 0x83; + VPDPage83Data.Reserved = 0; + VPDPage83Data.PageLength = sizeof(VPDPage83Data.IdDescriptorType1) + + sizeof(VPDPage83Data.IdDescriptorType2); + + /* T10 Vendor Identifier Field Format */ + /* VpdCodeSetAscii */ + VPDPage83Data.IdDescriptorType1.CodeSet = 2; + /* VpdIdentifierTypeVendorId */ + VPDPage83Data.IdDescriptorType1.IdentifierType = 1; + VPDPage83Data.IdDescriptorType1.IdentifierLength = +sizeof(VPDPage83Data.IdDescriptorType1) - 4; + + /* "ADAPTEC " for adaptec */ + memcpy(VPDPage83Data.Id
RE: [PATCH 4/7] aacraid: MSI-x support
Reviewed-by: Achim Leubner -Original Message- From: Mahesh Rajashekhara Sent: Wednesday, March 4, 2015 9:39 AM To: jbottom...@parallels.com; linux-scsi@vger.kernel.org Cc: aacr...@pmc-sierra.com; Harry Yang; Achim Leubner; Rajinikanth Pandurangan; Rich Bono; Mahesh Rajashekhara Subject: [PATCH 4/7] aacraid: MSI-x support Add MSI-x interrupt mode support. Signed-off-by: Mahesh Rajashekhara --- drivers/scsi/aacraid/aachba.c |6 +- drivers/scsi/aacraid/aacraid.h | 79 - drivers/scsi/aacraid/comminit.c | 86 +- drivers/scsi/aacraid/commsup.c | 19 ++- drivers/scsi/aacraid/dpcsup.c |9 +- drivers/scsi/aacraid/linit.c| 18 ++- drivers/scsi/aacraid/src.c | 365 +-- 7 files changed, 473 insertions(+), 109 deletions(-) diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 0819644..eb524e6 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -473,7 +473,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr) if ((le32_to_cpu(get_name_reply->status) == CT_OK) && (get_name_reply->data[0] != '\0')) { char *sp = get_name_reply->data; - sp[sizeof(((struct aac_get_name_resp *)NULL)->data)-1] = '\0'; + sp[sizeof(((struct aac_get_name_resp *)NULL)->data)] = '\0'; while (*sp == ' ') ++sp; if (*sp) { @@ -613,7 +613,9 @@ static void _aac_probe_container1(void * context, struct fib * fibptr) int status; dresp = (struct aac_mount *) fib_data(fibptr); - dresp->mnt[0].capacityhigh = 0; + if (!(fibptr->dev->supplement_adapter_info.SupportedOptions2 & + AAC_OPTION_VARIABLE_BLOCK_SIZE)) + dresp->mnt[0].capacityhigh = 0; if ((le32_to_cpu(dresp->status) != ST_OK) || (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) { _aac_probe_container2(context, fibptr); diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 93579f3..c162a65 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -6,11 +6,61 @@ #define nblank(x) _nblank(x)[0] #include +#include /*-- * D E F I N E S **/ +#define AAC_MAX_MSIX 32 /* vectors */ +#define AAC_PCI_MSI_ENABLE 0x8000 + +enum { + AAC_ENABLE_INTERRUPT= 0x0, + AAC_DISABLE_INTERRUPT, + AAC_ENABLE_MSIX, + AAC_DISABLE_MSIX, + AAC_CLEAR_AIF_BIT, + AAC_CLEAR_SYNC_BIT, + AAC_ENABLE_INTX +}; + +#define AAC_INT_MODE_INTX (1<<0) +#define AAC_INT_MODE_MSI (1<<1) +#define AAC_INT_MODE_AIF (1<<2) +#define AAC_INT_MODE_SYNC (1<<3) + +#define AAC_INT_ENABLE_TYPE1_INTX 0xfffb +#define AAC_INT_ENABLE_TYPE1_MSIX 0xfffa +#define AAC_INT_DISABLE_ALL0x + +/* Bit definitions in IOA->Host Interrupt Register */ +#define PMC_TRANSITION_TO_OPERATIONAL (0x8000 >> 0) +#define PMC_IOARCB_TRANSFER_FAILED (0x8000 >> 3) +#define PMC_IOA_UNIT_CHECK (0x8000 >> 4) +#define PMC_NO_HOST_RRQ_FOR_CMD_RESPONSE (0x8000 >> 5) +#define PMC_CRITICAL_IOA_OP_IN_PROGRESS(0x8000 >> 6) +#define PMC_IOARRIN_LOST (0x8000 >> 27) +#define PMC_SYSTEM_BUS_MMIO_ERROR (0x8000 >> 28) +#define PMC_IOA_PROCESSOR_IN_ERROR_STATE (0x8000 >> 29) +#define PMC_HOST_RRQ_VALID (0x8000 >> 30) +#define PMC_OPERATIONAL_STATUS (0x8000 >> 0) +#define PMC_ALLOW_MSIX_VECTOR0 (0x8000 >> 31) + +#define PMC_IOA_ERROR_INTERRUPTS (PMC_IOARCB_TRANSFER_FAILED | \ +PMC_IOA_UNIT_CHECK | \ +PMC_NO_HOST_RRQ_FOR_CMD_RESPONSE | \ +PMC_IOARRIN_LOST | \ +PMC_SYSTEM_BUS_MMIO_ERROR | \ +PMC_IOA_PROCESSOR_IN_ERROR_STATE) + +#define PMC_ALL_INTERRUPT_BITS (PMC_IOA_ERROR_INTERRUPTS | \ +PMC_HOST_RRQ_VALID | \ +PMC_TRANSITION_TO_OPERATIONAL | \ +PMC_ALLOW_MSIX_VECTOR0) +#definePMC_GLOBAL_INT_BIT2 0x0004 +#definePMC_GLOBAL_INT_BIT0 0x0001 + #ifndef AAC_DRIVER_BUILD # define AAC_DRIVER_BUILD 30300 # define AAC_DRIVER_BRANCH "-ms" @@ -36,6 +86,7 @@ #define CONTAINER_TO_ID(cont) (cont) #define CONTAINER_TO_LUN(cont) (0) +#define PMC_DEVICE_S6 0x28b #define PMC_DEVICE_S7 0x28c #define PMC_DEVICE_S8 0x28d #define PMC_DEVICE
[PATCH] scsi: sd: add a capacity_override attribute
This patch provides a sysfs interface allowing users to override the capacity of a SCSI disk. This will help in situations where a buggy USB-SATA adapter fails to support READ CAPACITY(16) and reports only the low 32 bits of the capacity in its READ CAPACITY(10) reply. For an example, see this thread: http://marc.info/?l=linux-scsi&m=140908235510961&w=2 The interface is awkward because it requires the user to tell the system to re-read the disk's partition table afterward, but at least it provides a way to handle deficient hardware. Signed-off-by: Alan Stern CC: Dale R. Worley --- [as1777] Documentation/ABI/testing/sysfs-class-scsi_disk | 19 drivers/scsi/sd.c | 37 drivers/scsi/sd.h |1 3 files changed, 57 insertions(+) Index: usb-4.0/Documentation/ABI/testing/sysfs-class-scsi_disk === --- /dev/null +++ usb-4.0/Documentation/ABI/testing/sysfs-class-scsi_disk @@ -0,0 +1,19 @@ +What: /sys/class/scsi_disk/HOST:CHANNEL:TARGET:LUN/capacity_override +Date: March 2015 +KernelVersion: 4.1 +Contact: Alan Stern +Description: + This file provides a way for users to override the + automatically determined disk capacity. For example, some + buggy USB-SATA adapters report only the low 32 bits of a + drive's block count, resulting in a calculated capacity + value that is the actual capacity modulo 2 TB. + + After the correct capacity (in native-size blocks -- often + 512 bytes per block but sometimes 4096) is written to this + file, the user must tell the system to re-read the disk's + partition table by running the command: + + /usr/sbin/blockdev --rereadpt /dev/sdX + + where X is the disk's drive letter. Index: usb-4.0/drivers/scsi/sd.h === --- usb-4.0.orig/drivers/scsi/sd.h +++ usb-4.0/drivers/scsi/sd.h @@ -66,6 +66,7 @@ struct scsi_disk { struct gendisk *disk; atomic_topeners; sector_tcapacity; /* size in 512-byte sectors */ + sector_tcapacity_override; /* in native-size blocks */ u32 max_xfer_blocks; u32 max_ws_blocks; u32 max_unmap_blocks; Index: usb-4.0/drivers/scsi/sd.c === --- usb-4.0.orig/drivers/scsi/sd.c +++ usb-4.0/drivers/scsi/sd.c @@ -477,6 +477,35 @@ max_write_same_blocks_store(struct devic } static DEVICE_ATTR_RW(max_write_same_blocks); +static ssize_t +capacity_override_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct scsi_disk *sdkp = to_scsi_disk(dev); + + return sprintf(buf, "%llu\n", + (unsigned long long) sdkp->capacity_override); +} + +static ssize_t +capacity_override_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct scsi_disk *sdkp = to_scsi_disk(dev); + unsigned long long cap; + int err; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + err = kstrtoull(buf, 10, &cap); + if (err) + return err; + sdkp->capacity_override = cap; + return count; +} +static DEVICE_ATTR_RW(capacity_override); + static struct attribute *sd_disk_attrs[] = { &dev_attr_cache_type.attr, &dev_attr_FUA.attr, @@ -489,6 +518,7 @@ static struct attribute *sd_disk_attrs[] &dev_attr_provisioning_mode.attr, &dev_attr_max_write_same_blocks.attr, &dev_attr_max_medium_access_timeouts.attr, + &dev_attr_capacity_override.attr, NULL, }; ATTRIBUTE_GROUPS(sd_disk); @@ -2152,6 +2182,13 @@ sd_read_capacity(struct scsi_disk *sdkp, struct scsi_device *sdp = sdkp->device; sector_t old_capacity = sdkp->capacity; + /* Did the user override the reported capacity? */ + if (!sdkp->first_scan && sdkp->capacity_override) { + sector_size = sdkp->device->sector_size; + sdkp->capacity = sdkp->capacity_override; + goto got_data; + } + if (sd_try_rc16_first(sdp)) { sector_size = read_capacity_16(sdkp, sdp, buffer); if (sector_size == -EOVERFLOW) -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
hyvää päivää
hyvää päivää Hanki laina tänään Loan Engine, jonka korko on 3%. täyttää Lomake jos kiinnostaa: Sukupuoli: Maa: Tarvittava määrä: Kesto: Mission: On monia syitä, miksi lainan voi auttaa terveiset Ana Paula -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 00/42] hpsa updates
These patches are based on Linus's tree The changes are: - make function names consistent - refactor functions - cleanup driver messages - cleanup error handling - clean up abort management - enhance sense data reporting - enhance ioaccel command support - add in block layer tag support - clean up resets - update copyright --- Don Brace (2): hpsa: change driver version hpsa: add PMC to copyright Joe Handzik (3): hpsa: use ioaccel2 path to submit IOs to physical drives in HBA mode. hpsa: Get queue depth from identify physical bmic for physical disks. hpsa: add more ioaccel2 error handling, including underrun statuses. Robert Elliott (18): hpsa: make function names consistent hpsa: print accurate SSD Smart Path Enabled status hpsa: break hpsa_free_irqs_and_disable_msix into two functions hpsa: clean up error handling hpsa: refactor freeing of resources into more logical functions hpsa: do not check cmd_alloc return value - it cannnot return NULL hpsa: correct return values from driver functions. hpsa: clean up driver init hpsa: clean up some error reporting output in abort handler hpsa: do not print ioaccel2 warning messages about unusual completions. hpsa: call pci_release_regions after pci_disable_device hpsa: skip free_irq calls if irqs are not allocated hpsa: cleanup for init_one step 2 in kdump hpsa: fix try_soft_reset error handling hpsa: create workqueue after the driver is ready for use hpsa: add interrupt number to /proc/interrupts interrupt name hpsa: use scsi host_no as hpsa controller number hpsa: propagate the error code in hpsa_kdump_soft_reset Stephen Cameron (9): hpsa: add masked physical devices into h->dev[] array hpsa: clean up aborts hpsa: decrement h->commands_outstanding in fail_all_outstanding_cmds hpsa: hpsa decode sense data for io and tmf hpsa: allow lockup detected to be viewed via sysfs hpsa: factor out hpsa_init_cmd function hpsa: do not ignore return value of hpsa_register_scsi hpsa: try resubmitting down raid path on task set full hpsa: add support sending aborts to physical devices via the ioaccel2 path Webb Scales (10): hpsa: clean up host, channel, target, lun prints hpsa: rework controller command submission hpsa: factor out hpsa_ioaccel_submit function hpsa: add ioaccel sg chaining for the ioaccel2 path hpsa: use helper routines for finishing commands hpsa: don't return abort request until target is complete hpsa: refactor and rework support for sending TEST_UNIT_READY hpsa: performance tweak for hpsa_scatter_gather() hpsa: use block layer tag for command allocation hpsa: cleanup reset drivers/scsi/hpsa.c | 2801 ++- drivers/scsi/hpsa.h | 22 drivers/scsi/hpsa_cmd.h | 37 + 3 files changed, 2052 insertions(+), 808 deletions(-) -- Signature -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 04/42] hpsa: clean up aborts
From: Stephen Cameron Do not send aborts to logical devices that do not support aborts Instead of relying on what the Smart Array claims for supporting logical drives, simply try an abort and see how it responds at device discovery time. This way devices that do support aborts (e.g. MSA2000) can work and we do not waste time trying to send aborts to logical drives that do not support them (important for high IOPS devices.) While rescanning devices only test whether devices support aborts the first time we encounter a device rather than every time. Some Smart Arrays required aborts to be sent with tags in the wrong endian byte order. To avoid having to know about this, we would send two aborts with tags with each endian order. On high IOPS devices, this turns out to be not such a hot idea. So we now have a list of the devices that got the tag backwards, and we only send it one way. If all available commands are outstanding and the abort handler is invoked, the abort handler may not be able to allocate a command and may busy-wait excessivly. Reserve a small number of commands for the abort handler and limit the number of concurrent abort requests to the number of reserved commands. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 176 +-- drivers/scsi/hpsa.h |4 + 2 files changed, 147 insertions(+), 33 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 488f81b..fe860a6 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -428,7 +428,7 @@ static ssize_t host_show_hp_ssd_smart_path_status(struct device *dev, /* List of controllers which cannot be hard reset on kexec with reset_devices */ static u32 unresettable_controller[] = { 0x324a103C, /* Smart Array P712m */ - 0x324b103C, /* SmartArray P711m */ + 0x324b103C, /* Smart Array P711m */ 0x3223103C, /* Smart Array P800 */ 0x3234103C, /* Smart Array P400 */ 0x3235103C, /* Smart Array P400i */ @@ -470,24 +470,32 @@ static u32 soft_unresettable_controller[] = { 0x409D0E11, /* Smart Array 6400 EM */ }; -static int ctlr_is_hard_resettable(u32 board_id) +static u32 needs_abort_tags_swizzled[] = { + 0x323D103C, /* Smart Array P700m */ + 0x324a103C, /* Smart Array P712m */ + 0x324b103C, /* SmartArray P711m */ +}; + +static int board_id_in_array(u32 a[], int nelems, u32 board_id) { int i; - for (i = 0; i < ARRAY_SIZE(unresettable_controller); i++) - if (unresettable_controller[i] == board_id) - return 0; - return 1; + for (i = 0; i < nelems; i++) + if (a[i] == board_id) + return 1; + return 0; } -static int ctlr_is_soft_resettable(u32 board_id) +static int ctlr_is_hard_resettable(u32 board_id) { - int i; + return !board_id_in_array(unresettable_controller, + ARRAY_SIZE(unresettable_controller), board_id); +} - 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_soft_resettable(u32 board_id) +{ + return !board_id_in_array(soft_unresettable_controller, + ARRAY_SIZE(soft_unresettable_controller), board_id); } static int ctlr_is_resettable(u32 board_id) @@ -496,6 +504,12 @@ static int ctlr_is_resettable(u32 board_id) ctlr_is_soft_resettable(board_id); } +static int ctlr_needs_abort_tags_swizzled(u32 board_id) +{ + return board_id_in_array(needs_abort_tags_swizzled, + ARRAY_SIZE(needs_abort_tags_swizzled), board_id); +} + static ssize_t host_show_resettable(struct device *dev, struct device_attribute *attr, char *buf) { @@ -2838,6 +2852,50 @@ static int hpsa_volume_offline(struct ctlr_info *h, return 0; } +/* + * Find out if a logical device supports aborts by simply trying one. + * Smart Array may claim not to support aborts on logical drives, but + * if a MSA2000 * is connected, the drives on that will be presented + * by the Smart Array as logical drives, and aborts may be sent to + * those devices successfully. So the simplest way to find out is + * to simply try an abort and see how the device responds. + */ +static int hpsa_device_supports_aborts(struct ctlr_info *h, + unsigned char *scsi3addr) +{ + struct CommandList *c; + struct ErrorInfo *ei; + int rc = 0; + + u64 tag = (u64) -1; /* bogus tag */ + + /* Assume that physical devices support aborts */ + if (!is_logical_dev_addr_mode(scsi3addr)) + return 1; + + c = cmd_alloc(h); + if (!c) + return -ENOMEM; + (void) fill_cmd(c, HPSA_ABORT_MSG, h, &tag, 0, 0, scsi3addr, TYPE_MSG); +
[PATCH v3 06/42] hpsa: hpsa decode sense data for io and tmf
From: Stephen Cameron In hba mode, we could get sense data in descriptor format so we need to handle that. It's possible for CommandStatus to have value 0x0D "TMF Function Status", which we should handle. We will get this from a P1224 when aborting a non-existent tag, for example. The "ScsiStatus" field of the errinfo field will contain the TMF function status value. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 143 +++ drivers/scsi/hpsa_cmd.h |9 +++ 2 files changed, 117 insertions(+), 35 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 3a06812..415ec4d 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -268,16 +269,49 @@ static inline struct ctlr_info *shost_to_hba(struct Scsi_Host *sh) return (struct ctlr_info *) *priv; } +/* extract sense key, asc, and ascq from sense data. -1 means invalid. */ +static void decode_sense_data(const u8 *sense_data, int sense_data_len, + int *sense_key, int *asc, int *ascq) +{ + struct scsi_sense_hdr sshdr; + bool rc; + + *sense_key = -1; + *asc = -1; + *ascq = -1; + + if (sense_data_len < 1) + return; + + rc = scsi_normalize_sense(sense_data, sense_data_len, &sshdr); + if (rc) { + *sense_key = sshdr.sense_key; + *asc = sshdr.asc; + *ascq = sshdr.ascq; + } +} + static int check_for_unit_attention(struct ctlr_info *h, struct CommandList *c) { - if (c->err_info->SenseInfo[2] != UNIT_ATTENTION) + int sense_key, asc, ascq; + int sense_len; + + if (c->err_info->SenseLen > sizeof(c->err_info->SenseInfo)) + sense_len = sizeof(c->err_info->SenseInfo); + else + sense_len = c->err_info->SenseLen; + + decode_sense_data(c->err_info->SenseInfo, sense_len, + &sense_key, &asc, &ascq); + if (sense_key != UNIT_ATTENTION || asc == -1) return 0; - switch (c->err_info->SenseInfo[12]) { + switch (asc) { case STATE_CHANGED: - dev_warn(&h->pdev->dev, HPSA "%d: a state change " - "detected, command retried\n", h->ctlr); + dev_warn(&h->pdev->dev, + HPSA "%d: a state change detected, command retried\n", + h->ctlr); break; case LUN_FAILED: dev_warn(&h->pdev->dev, @@ -1890,6 +1924,34 @@ retry_cmd: queue_work_on(raw_smp_processor_id(), h->resubmit_wq, &c->work); } +/* Returns 0 on success, < 0 otherwise. */ +static int hpsa_evaluate_tmf_status(struct ctlr_info *h, + struct CommandList *cp) +{ + u8 tmf_status = cp->err_info->ScsiStatus; + + switch (tmf_status) { + case CISS_TMF_COMPLETE: + /* +* CISS_TMF_COMPLETE never happens, instead, +* ei->CommandStatus == 0 for this case. +*/ + case CISS_TMF_SUCCESS: + return 0; + case CISS_TMF_INVALID_FRAME: + case CISS_TMF_NOT_SUPPORTED: + case CISS_TMF_FAILED: + case CISS_TMF_WRONG_LUN: + case CISS_TMF_OVERLAPPED_TAG: + break; + default: + dev_warn(&h->pdev->dev, "Unknown TMF status: 0x%02x\n", + tmf_status); + break; + } + return -tmf_status; +} + static void complete_scsi_command(struct CommandList *cp) { struct scsi_cmnd *cmd; @@ -1897,9 +1959,9 @@ static void complete_scsi_command(struct CommandList *cp) struct ErrorInfo *ei; struct hpsa_scsi_dev_t *dev; - unsigned char sense_key; - unsigned char asc; /* additional sense code */ - unsigned char ascq; /* additional sense code qualifier */ + int sense_key; + int asc; /* additional sense code */ + int ascq; /* additional sense code qualifier */ unsigned long sense_data_size; ei = cp->err_info; @@ -1934,8 +1996,6 @@ static void complete_scsi_command(struct CommandList *cp) if (cp->cmd_type == CMD_IOACCEL2) return process_ioaccel2_completion(h, cp, cmd, dev); - cmd->result |= ei->ScsiStatus; - scsi_set_resid(cmd, ei->ResidualCnt); if (ei->CommandStatus == 0) { if (cp->cmd_type == CMD_IOACCEL1) @@ -1945,16 +2005,6 @@ static void complete_scsi_command(struct CommandList *cp) return; } - /* copy the sense data */ - if (SCSI_SENSE_BUFFERSIZE < sizeof(ei->SenseInfo)) - sense_data_size = SCSI_SENSE_BUFFERSIZE; - else - sense_data_size = sizeof(ei->SenseInf
[PATCH v3 03/42] hpsa: rework controller command submission
From: Webb Scales Allow driver initiated commands to have a timeout. It does not yet try to do anything with timeouts on such commands. We are sending a reset in order to get rid of a command we want to abort. If we make it return on the same reply queue as the command we want to abort, the completion of the aborted command will not race with the completion of the reset command. Rename hpsa_scsi_do_simple_cmd_core() to hpsa_scsi_do_simple_cmd(), since this function is the interface for issuing commands to the controller and not the "core" of that implementation. Add a parameter to it which allows the caller to specify the reply queue to be used. Modify existing callers to specify the default reply queue. Rename __hpsa_scsi_do_simple_cmd_core() to hpsa_scsi_do_simple_cmd_core(), since this routine is the "core" implementation of the "do simple command" function and there is no longer any other function with a similar name. Modify the existing callers of this routine (other than hpsa_scsi_do_simple_cmd()) to instead call hpsa_scsi_do_simple_cmd(), since it will now accept the reply_queue paramenter, and it provides a controller lock-up check. (Also, tweak two related message strings to make them distinct from each other.) Submitting a command to a locked up controller always results in a timeout, so check for controller lock-up before submitting. This is to enable fixing a race between command completions and abort completions on different reply queues in a subsequent patch. We want to be able to specify which reply queue an abort completion should occur on so that it cannot race the completion of the command it is trying to abort. The following race was possible in theory: 1. Abort command is sent to hardware. 2. Command to be aborted simultaneously completes on another reply queue. 3. Hardware receives abort command, decides command has already completed and indicates this to the driver via another different reply queue. 4. driver processes abort completion finds that the hardware does not know about the command, concludes that therefore the command cannot complete, returns SUCCESS indicating to the mid-layer that the scsi_cmnd may be re-used. 5. Command from step 2 is processed and completed back to scsi mid layer (after we already promised that would never happen.) Fix by forcing aborts to complete on the same reply queue as the command they are aborting. Piggybacking device rescanning functionality onto the lockup detection thread is not a good idea because if the controller locks up during device rescanning, then the thread could get stuck, then the lockup isn't detected. Use separate work queues for device rescanning and lockup detection. Detect controller lockup in abort handler. After a lockup is detected, return DO_NO_CONNECT which results in immediate termination of commands rather than DID_ERR which results in retries. Modify detect_controller_lockup() to return the result, to remove the need for a separate check. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Webb Scales Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 326 --- drivers/scsi/hpsa_cmd.h |5 + 2 files changed, 254 insertions(+), 77 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 9b88726..488f81b 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -253,6 +253,8 @@ static int hpsa_scsi_ioaccel_queue_command(struct ctlr_info *h, struct CommandList *c, u32 ioaccel_handle, u8 *cdb, int cdb_len, u8 *scsi3addr, struct hpsa_scsi_dev_t *phys_disk); static void hpsa_command_resubmit_worker(struct work_struct *work); +static u32 lockup_detected(struct ctlr_info *h); +static int detect_controller_lockup(struct ctlr_info *h); static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev) { @@ -748,30 +750,43 @@ static inline u32 next_command(struct ctlr_info *h, u8 q) * a separate special register for submitting commands. */ -/* set_performant_mode: Modify the tag for cciss performant +/* + * set_performant_mode: Modify the tag for cciss performant * set bit 0 for pull model, bits 3-1 for block fetch * register number */ -static void set_performant_mode(struct ctlr_info *h, struct CommandList *c) +#define DEFAULT_REPLY_QUEUE (-1) +static void set_performant_mode(struct ctlr_info *h, struct CommandList *c, + int reply_queue) { if (likely(h->transMethod & CFGTBL_Trans_Performant)) { c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1); - if (likely(h->msix_vector > 0)) + if (unlikely(!h->msix_vector)) + return; + if (likely(reply_queue == DEFAULT_REPLY_QUEUE)) c->Header.ReplyQueue = raw_smp_processor_id() % h->nreply_queues; +
[PATCH v3 01/42] hpsa: add masked physical devices into h->dev[] array
From: Stephen Cameron Cache the ioaccel handle so that when we need to abort commands sent down the ioaccel2 path, we can look up the LUN ID in h->dev[] instead of having to do I/O to the controller. Add a field to elements in h->dev[] to keep track of how the device is exposed to the SCSI mid layer: Not at all, without an upper level driver (no_uld_attach) or normally exposed. Since masked physical devices are now present in h->dev[] array it would be perfectly possible to do echo scsi add-single-device 2 2 0 0 > /proc/scsi/scsi and bring them online. This was previously not allowed for masked physical devices. Ensure that the mapping of physical disks to logical drives gets updated in a consistent way when a RAID migration occurs and is not touched until updates to it are complete. now instead of doing CISS_REPORT_PHYSICAL to get the LUNID for the physical disk in hpsa_get_pdisk_of_ioaccel2(), just get it out of h->dev[] where we already have it cached. do not touch phys_disk[] for ioaccel enabled logical drives during rescan Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 253 +-- drivers/scsi/hpsa.h |6 + drivers/scsi/hpsa_cmd.h |3 + 3 files changed, 141 insertions(+), 121 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index a1cfbd3..3417b8b 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -222,6 +222,7 @@ static int hpsa_change_queue_depth(struct scsi_device *sdev, int qdepth); static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd); static int hpsa_eh_abort_handler(struct scsi_cmnd *scsicmd); static int hpsa_slave_alloc(struct scsi_device *sdev); +static int hpsa_slave_configure(struct scsi_device *sdev); static void hpsa_slave_destroy(struct scsi_device *sdev); static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno); @@ -667,6 +668,9 @@ static struct device_attribute *hpsa_shost_attrs[] = { NULL, }; +#define HPSA_NRESERVED_CMDS(HPSA_CMDS_RESERVED_FOR_ABORTS + \ + HPSA_CMDS_RESERVED_FOR_DRIVER + HPSA_MAX_CONCURRENT_PASSTHRUS) + static struct scsi_host_template hpsa_driver_template = { .module = THIS_MODULE, .name = HPSA, @@ -681,6 +685,7 @@ static struct scsi_host_template hpsa_driver_template = { .eh_device_reset_handler = hpsa_eh_device_reset_handler, .ioctl = hpsa_ioctl, .slave_alloc= hpsa_slave_alloc, + .slave_configure= hpsa_slave_configure, .slave_destroy = hpsa_slave_destroy, #ifdef CONFIG_COMPAT .compat_ioctl = hpsa_compat_ioctl, @@ -946,6 +951,8 @@ lun_assigned: h->dev[n] = device; h->ndevices++; + device->offload_to_be_enabled = device->offload_enabled; + device->offload_enabled = 0; added[*nadded] = device; (*nadded)++; @@ -982,16 +989,20 @@ static void hpsa_scsi_update_entry(struct ctlr_info *h, int hostno, */ h->dev[entry]->raid_map = new_entry->raid_map; h->dev[entry]->ioaccel_handle = new_entry->ioaccel_handle; - wmb(); /* ensure raid map updated prior to ->offload_enabled */ } h->dev[entry]->offload_config = new_entry->offload_config; h->dev[entry]->offload_to_mirror = new_entry->offload_to_mirror; - h->dev[entry]->offload_enabled = new_entry->offload_enabled; h->dev[entry]->queue_depth = new_entry->queue_depth; - dev_info(&h->pdev->dev, "%s device c%db%dt%dl%d updated.\n", - scsi_device_type(new_entry->devtype), hostno, new_entry->bus, - new_entry->target, new_entry->lun); + /* +* We can turn off ioaccel offload now, but need to delay turning +* it on until we can update h->dev[entry]->phys_disk[], but we +* can't do that until all the devices are updated. +*/ + h->dev[entry]->offload_to_be_enabled = new_entry->offload_enabled; + if (!new_entry->offload_enabled) + h->dev[entry]->offload_enabled = 0; + } /* Replace an entry from h->dev[] array. */ @@ -1014,6 +1025,8 @@ static void hpsa_scsi_replace_entry(struct ctlr_info *h, int hostno, new_entry->lun = h->dev[entry]->lun; } + new_entry->offload_to_be_enabled = new_entry->offload_enabled; + new_entry->offload_enabled = 0; h->dev[entry] = new_entry; added[*nadded] = new_entry; (*nadded)++; @@ -1312,7 +1325,8 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h, */ if (!logical_drive->phys_disk[i]) { logical_drive->offload_enabled = 0; - logical_drive->queue_depth = h->nr_cmds; + logical_drive->offload_to_be_enabled = 0; +
[PATCH v3 05/42] hpsa: decrement h->commands_outstanding in fail_all_outstanding_cmds
From: Stephen Cameron make tracking of outstanding commands more robust Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/hpsa.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index fe860a6..3a06812 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -6945,7 +6945,7 @@ static void fail_all_outstanding_cmds(struct ctlr_info *h) if (refcount > 1) { c->err_info->CommandStatus = CMD_CTLR_LOCKUP; finish_cmd(c); - failcount++; + atomic_dec(&h->commands_outstanding); } cmd_free(h, c); } -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 02/42] hpsa: clean up host, channel, target, lun prints
From: Webb Scales We had a mix of formats used for specifying controller, bus, target, and lun address of devices. change to the format used by the scsi midlayer and upper layer (2:3:0:0) so you can easily follow the information from hpsa to scsi midlayer to sd upper layer. Also add this information: - product ID - vendor ID - RAID level - SSD Smath Path capable and enabled - exposure level (sg-only) Example: hpsa :04:00.0: added scsi 2:0:0:0: Direct-Access HP LOGICAL VOLUME RAID-0 SSDSmartPathCap+ En+ Exp=4 scsi 2:0:0:0: Direct-Access HP LOGICAL VOLUME 10.0 PQ: 0 ANSI: 5 sd 2:0:0:0: [sdr] 12501713072 512-byte logical blocks: (6.40 TB/5.82 TiB) sd 2:0:0:0: [sdr] 4096-byte physical blocks sd 2:0:0:0: [sdr] Attached SCSI disk sd 2:0:0:0: Attached scsi generic sg20 type 0 Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Robert Elliott Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 103 +++ 1 file changed, 71 insertions(+), 32 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 3417b8b..9b88726 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -886,6 +886,53 @@ static int hpsa_find_target_lun(struct ctlr_info *h, return !found; } +static inline void hpsa_show_dev_msg(int type, struct ctlr_info *h, + struct hpsa_scsi_dev_t *dev, char *description) +{ +#define HPSA_INFO 0 +#define HPSA_WARN 1 +#define HPSA_ERR 2 + if (type == HPSA_INFO) + dev_info(&h->pdev->dev, + "scsi %d:%d:%d:%d: %s %s %.8s %.16s RAID-%s SSDSmartPathCap%c En%c Exp=%d\n", + h->scsi_host->host_no, dev->bus, dev->target, dev->lun, + description, + scsi_device_type(dev->devtype), + dev->vendor, + dev->model, + dev->raid_level > RAID_UNKNOWN ? + "RAID-?" : raid_label[dev->raid_level], + dev->offload_config ? '+' : '-', + dev->offload_enabled ? '+' : '-', + dev->expose_state); + else if (type == HPSA_WARN) + dev_warn(&h->pdev->dev, + "scsi %d:%d:%d:%d: %s %s %.8s %.16s RAID-%s SSDSmartPathCap%c En%c Exp=%d\n", + h->scsi_host->host_no, dev->bus, dev->target, dev->lun, + description, + scsi_device_type(dev->devtype), + dev->vendor, + dev->model, + dev->raid_level > RAID_UNKNOWN ? + "RAID-?" : raid_label[dev->raid_level], + dev->offload_config ? '+' : '-', + dev->offload_enabled ? '+' : '-', + dev->expose_state); + else if (type == HPSA_ERR) + dev_err(&h->pdev->dev, + "scsi %d:%d:%d:%d: %s %s %.8s %.16s RAID-%s SSDSmartPathCap%c En%c Exp=%d\n", + h->scsi_host->host_no, dev->bus, dev->target, dev->lun, + description, + scsi_device_type(dev->devtype), + dev->vendor, + dev->model, + dev->raid_level > RAID_UNKNOWN ? + "RAID-?" : raid_label[dev->raid_level], + dev->offload_config ? '+' : '-', + dev->offload_enabled ? '+' : '-', + dev->expose_state); +} + /* Add an entry into h->dev[] array. */ static int hpsa_scsi_add_entry(struct ctlr_info *h, int hostno, struct hpsa_scsi_dev_t *device, @@ -955,15 +1002,8 @@ lun_assigned: device->offload_enabled = 0; added[*nadded] = device; (*nadded)++; - - /* initially, (before registering with scsi layer) we don't -* know our hostno and we don't want to print anything first -* time anyway (the scsi layer's inquiries will show that info) -*/ - /* if (hostno != -1) */ - dev_info(&h->pdev->dev, "%s device c%db%dt%dl%d added.\n", - scsi_device_type(device->devtype), hostno, - device->bus, device->target, device->lun); + hpsa_show_dev_msg(HPSA_INFO, h, device, + device->expose_state & HPSA_SCSI_ADD ? "added" : "masked"); return 0; } @@ -1003,6 +1043,7 @@ static void hpsa_scsi_update_entry(struct ctlr_info *h, int hostno, if (!new_entry->offload_enabled) h->dev[entry]->offload_enabled = 0; + hpsa_show_dev_msg(HPSA_INFO, h, h->dev[entry], "updated"); } /* Replace an entry from h->dev[] array. */ @@ -1030,9 +1071,7 @@ static void hpsa_scsi_replace_entry(struct ctlr_info *h, int hostno, h->dev[entry] = new_entry; added[*nadded] = new_entry; (*nadded)++;
[PATCH v3 10/42] hpsa: do not ignore return value of hpsa_register_scsi
From: Stephen Cameron add error handling for failure when registering with SCSI subsystem. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/hpsa.c |4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index d57fa4b..15bf3bcb 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -7453,7 +7453,9 @@ reinit_after_soft_reset: h->access.set_intr_mask(h, HPSA_INTR_ON); hpsa_hba_inquiry(h); - hpsa_register_scsi(h); /* hook ourselves into SCSI subsystem */ + rc = hpsa_register_scsi(h); /* hook ourselves into SCSI subsystem */ + if (rc) + goto clean4; /* Monitor the controller for firmware lockups */ h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL; -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 09/42] hpsa: factor out hpsa_init_cmd function
From: Stephen Cameron Factor out hpsa_cmd_init from cmd_alloc(). We also need this for resubmitting commands down the default RAID path when they have returned from the ioaccel paths with errors. In particular, reinitialize the cmd_type and busaddr fields as these will not be correct for submitting down the RAID stack path after ioaccel command completion. This saves time when submitting commands. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 77 --- drivers/scsi/hpsa_cmd.h |2 + 2 files changed, 53 insertions(+), 26 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 9a13525..d57fa4b 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -4317,7 +4317,6 @@ static int hpsa_ciss_submit(struct ctlr_info *h, /* Fill in the request block... */ c->Request.Timeout = 0; - memset(c->Request.CDB, 0, sizeof(c->Request.CDB)); BUG_ON(cmd->cmd_len > sizeof(c->Request.CDB)); c->Request.CDBLen = cmd->cmd_len; memcpy(c->Request.CDB, cmd->cmnd, cmd->cmd_len); @@ -4368,6 +4367,48 @@ static int hpsa_ciss_submit(struct ctlr_info *h, return 0; } +static void hpsa_cmd_init(struct ctlr_info *h, int index, + struct CommandList *c) +{ + dma_addr_t cmd_dma_handle, err_dma_handle; + + /* Zero out all of commandlist except the last field, refcount */ + memset(c, 0, offsetof(struct CommandList, refcount)); + c->Header.tag = cpu_to_le64((u64) (index << DIRECT_LOOKUP_SHIFT)); + cmd_dma_handle = h->cmd_pool_dhandle + index * sizeof(*c); + c->err_info = h->errinfo_pool + index; + memset(c->err_info, 0, sizeof(*c->err_info)); + err_dma_handle = h->errinfo_pool_dhandle + + index * sizeof(*c->err_info); + c->cmdindex = index; + c->busaddr = (u32) cmd_dma_handle; + c->ErrDesc.Addr = cpu_to_le64((u64) err_dma_handle); + c->ErrDesc.Len = cpu_to_le32((u32) sizeof(*c->err_info)); + c->h = h; +} + +static void hpsa_preinitialize_commands(struct ctlr_info *h) +{ + int i; + + for (i = 0; i < h->nr_cmds; i++) { + struct CommandList *c = h->cmd_pool + i; + + hpsa_cmd_init(h, i, c); + atomic_set(&c->refcount, 0); + } +} + +static inline void hpsa_cmd_partial_init(struct ctlr_info *h, int index, + struct CommandList *c) +{ + dma_addr_t cmd_dma_handle = h->cmd_pool_dhandle + index * sizeof(*c); + + memset(c->Request.CDB, 0, sizeof(c->Request.CDB)); + memset(c->err_info, 0, sizeof(*c->err_info)); + c->busaddr = (u32) cmd_dma_handle; +} + static void hpsa_command_resubmit_worker(struct work_struct *work) { struct scsi_cmnd *cmd; @@ -4382,6 +4423,7 @@ static void hpsa_command_resubmit_worker(struct work_struct *work) cmd->scsi_done(cmd); return; } + hpsa_cmd_partial_init(c->h, c->cmdindex, c); if (hpsa_ciss_submit(c->h, c, cmd, dev->scsi3addr)) { /* * If we get here, it means dma mapping failed. Try @@ -4438,10 +4480,11 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd) h->acciopath_status)) { cmd->host_scribble = (unsigned char *) c; - c->cmd_type = CMD_SCSI; - c->scsi_cmd = cmd; if (dev->offload_enabled) { + hpsa_cmd_init(h, c->cmdindex, c); + c->cmd_type = CMD_SCSI; + c->scsi_cmd = cmd; rc = hpsa_scsi_ioaccel_raid_map(h, c); if (rc == 0) return 0; /* Sent on ioaccel path */ @@ -4450,6 +4493,9 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd) return SCSI_MLQUEUE_HOST_BUSY; } } else if (dev->ioaccel_handle) { + hpsa_cmd_init(h, c->cmdindex, c); + c->cmd_type = CMD_SCSI; + c->scsi_cmd = cmd; rc = hpsa_scsi_ioaccel_direct_map(h, c); if (rc == 0) return 0; /* Sent on direct map path */ @@ -5061,10 +5107,7 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc) static struct CommandList *cmd_alloc(struct ctlr_info *h) { struct CommandList *c; - int i; - union u64bit temp64; - dma_addr_t cmd_dma_handle, err_dma_handle; - int refcount; + int refcount, i; unsigned long offset; /* @@ -5098,24 +5141,7 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h) break; /* it's ours now. */ } h->last_allocation = i; /* benignly racy */ - - /
[PATCH v3 08/42] hpsa: make function names consistent
From: Robert Elliott make function names more consistent and meaningful Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Robert Elliott Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 14 -- 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index f84d63f..9a13525 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -6817,7 +6817,7 @@ out_disable: return rc; } -static int hpsa_allocate_cmd_pool(struct ctlr_info *h) +static int hpsa_alloc_cmd_pool(struct ctlr_info *h) { h->cmd_pool_bits = kzalloc( DIV_ROUND_UP(h->nr_cmds, BITS_PER_LONG) * @@ -7347,7 +7347,7 @@ reinit_after_soft_reset: 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"); - rc = hpsa_allocate_cmd_pool(h); + rc = hpsa_alloc_cmd_pool(h); if (rc) goto clean2_and_free_irqs; if (hpsa_allocate_sg_chain_blocks(h)) @@ -7794,7 +7794,8 @@ static int hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support) return 0; } -static int hpsa_alloc_ioaccel_cmd_and_bft(struct ctlr_info *h) +/* Allocate ioaccel1 mode command blocks and block fetch table */ +static int hpsa_alloc_ioaccel1_cmd_and_bft(struct ctlr_info *h) { h->ioaccel_maxsg = readl(&(h->cfgtable->io_accel_max_embedded_sg_count)); @@ -7833,7 +7834,8 @@ clean_up: return 1; } -static int ioaccel2_alloc_cmds_and_bft(struct ctlr_info *h) +/* Allocate ioaccel2 mode command blocks and block fetch table */ +static int hpsa_alloc_ioaccel2_cmd_and_bft(struct ctlr_info *h) { /* Allocate ioaccel2 mode command blocks and block fetch table */ @@ -7888,13 +7890,13 @@ static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h) if (trans_support & CFGTBL_Trans_io_accel1) { transMethod |= CFGTBL_Trans_io_accel1 | CFGTBL_Trans_enable_directed_msix; - if (hpsa_alloc_ioaccel_cmd_and_bft(h)) + if (hpsa_alloc_ioaccel1_cmd_and_bft(h)) goto clean_up; } else { if (trans_support & CFGTBL_Trans_io_accel2) { transMethod |= CFGTBL_Trans_io_accel2 | CFGTBL_Trans_enable_directed_msix; - if (ioaccel2_alloc_cmds_and_bft(h)) + if (hpsa_alloc_ioaccel2_cmd_and_bft(h)) goto clean_up; } } -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 07/42] hpsa: allow lockup detected to be viewed via sysfs
From: Stephen Cameron expose a detected lockup via sysfs Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 415ec4d..f84d63f 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -351,6 +351,20 @@ static int check_for_busy(struct ctlr_info *h, struct CommandList *c) return 1; } +static u32 lockup_detected(struct ctlr_info *h); +static ssize_t host_show_lockup_detected(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ld; + struct ctlr_info *h; + struct Scsi_Host *shost = class_to_shost(dev); + + h = shost_to_hba(shost); + ld = lockup_detected(h); + + return sprintf(buf, "ld=%d\n", ld); +} + static ssize_t host_store_hp_ssd_smart_path_status(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -698,12 +712,15 @@ static DEVICE_ATTR(transport_mode, S_IRUGO, host_show_transport_mode, NULL); static DEVICE_ATTR(resettable, S_IRUGO, host_show_resettable, NULL); +static DEVICE_ATTR(lockup_detected, S_IRUGO, + host_show_lockup_detected, NULL); static struct device_attribute *hpsa_sdev_attrs[] = { &dev_attr_raid_level, &dev_attr_lunid, &dev_attr_unique_id, &dev_attr_hp_ssd_smart_path_enabled, + &dev_attr_lockup_detected, NULL, }; -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 14/42] hpsa: use ioaccel2 path to submit IOs to physical drives in HBA mode.
From: Joe Handzik use ioaccel2 path to submit I/O to physical drives in HBA mode Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Joe Handzik Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 10 +- drivers/scsi/hpsa.h |1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index e9d3d71..76f9042 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1123,6 +1123,11 @@ static void hpsa_scsi_update_entry(struct ctlr_info *h, int hostno, h->dev[entry]->raid_map = new_entry->raid_map; h->dev[entry]->ioaccel_handle = new_entry->ioaccel_handle; } + if (new_entry->hba_ioaccel_enabled) { + h->dev[entry]->ioaccel_handle = new_entry->ioaccel_handle; + wmb(); /* set ioaccel_handle *before* hba_ioaccel_enabled */ + } + h->dev[entry]->hba_ioaccel_enabled = new_entry->hba_ioaccel_enabled; h->dev[entry]->offload_config = new_entry->offload_config; h->dev[entry]->offload_to_mirror = new_entry->offload_to_mirror; h->dev[entry]->queue_depth = new_entry->queue_depth; @@ -3039,6 +3044,7 @@ static int hpsa_update_device_info(struct ctlr_info *h, this_device->offload_config = 0; this_device->offload_enabled = 0; this_device->offload_to_be_enabled = 0; + this_device->hba_ioaccel_enabled = 0; this_device->volume_offline = 0; this_device->queue_depth = h->nr_cmds; } @@ -3327,6 +,8 @@ static void hpsa_get_ioaccel_drive_info(struct ctlr_info *h, (struct ext_report_lun_entry *) lunaddrbytes; dev->ioaccel_handle = rle->ioaccel_handle; + if (PHYS_IOACCEL(lunaddrbytes) && dev->ioaccel_handle) + dev->hba_ioaccel_enabled = 1; memset(id_phys, 0, sizeof(*id_phys)); rc = hpsa_bmic_id_physical_device(h, lunaddrbytes, GET_BMIC_DRIVE_NUMBER(lunaddrbytes), id_phys, @@ -4428,7 +4436,7 @@ static int hpsa_ioaccel_submit(struct ctlr_info *h, rc = hpsa_scsi_ioaccel_raid_map(h, c); if (rc < 0) /* scsi_dma_map failed. */ rc = SCSI_MLQUEUE_HOST_BUSY; - } else if (dev->ioaccel_handle) { + } else if (dev->hba_ioaccel_enabled) { hpsa_cmd_init(h, c->cmdindex, c); c->cmd_type = CMD_SCSI; c->scsi_cmd = cmd; diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index df2468c..87a70b5 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -55,6 +55,7 @@ struct hpsa_scsi_dev_t { int offload_config; /* I/O accel RAID offload configured */ int offload_enabled;/* I/O accel RAID offload enabled */ int offload_to_be_enabled; + int hba_ioaccel_enabled; int offload_to_mirror; /* Send next I/O accelerator RAID * offload request to mirror drive */ -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 22/42] hpsa: correct return values from driver functions.
From: Robert Elliott correct return codes for error conditions Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Robert Elliott Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 886e928..2cb4db7 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -2691,9 +2691,9 @@ static int hpsa_get_raid_map(struct ctlr_info *h, if (fill_cmd(c, HPSA_GET_RAID_MAP, h, &this_device->raid_map, sizeof(this_device->raid_map), 0, scsi3addr, TYPE_CMD)) { - dev_warn(&h->pdev->dev, "Out of memory in hpsa_get_raid_map()\n"); - rc = -ENOMEM; - goto out; + dev_warn(&h->pdev->dev, "hpsa_get_raid_map fill_cmd failed\n"); + cmd_free(h, c); + return -1; } rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE, NO_TIMEOUT); @@ -5455,7 +5455,7 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp) if (iocommand.buf_size > 0) { buff = kmalloc(iocommand.buf_size, GFP_KERNEL); if (buff == NULL) - return -EFAULT; + return -ENOMEM; if (iocommand.Request.Type.Direction & XFER_WRITE) { /* Copy the data into the buffer we created */ if (copy_from_user(buff, iocommand.buf, @@ -8002,7 +8002,7 @@ static int hpsa_alloc_ioaccel1_cmd_and_bft(struct ctlr_info *h) clean_up: hpsa_free_ioaccel1_cmd_and_bft(h); - return 1; + return -ENOMEM; } /* Free ioaccel2 mode command blocks and block fetch table */ -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 21/42] hpsa: do not check cmd_alloc return value - it cannnot return NULL
From: Robert Elliott cmd_alloc can no longer return NULL, so don't check for NULL any more (which is unreachable code). Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Robert Elliott Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 77 ++- 1 file changed, 15 insertions(+), 62 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index ba89375a..886e928 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -2504,11 +2504,6 @@ static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr, c = cmd_alloc(h); - if (c == NULL) { - dev_warn(&h->pdev->dev, "cmd_alloc returned NULL!\n"); - return -ENOMEM; - } - if (fill_cmd(c, HPSA_INQUIRY, h, buf, bufsize, page, scsi3addr, TYPE_CMD)) { rc = -1; @@ -2537,11 +2532,6 @@ static int hpsa_bmic_ctrl_mode_sense(struct ctlr_info *h, struct ErrorInfo *ei; c = cmd_alloc(h); - if (c == NULL) {/* trouble... */ - dev_warn(&h->pdev->dev, "cmd_alloc returned NULL!\n"); - return -ENOMEM; - } - if (fill_cmd(c, BMIC_SENSE_CONTROLLER_PARAMETERS, h, buf, bufsize, page, scsi3addr, TYPE_CMD)) { rc = -1; @@ -2559,7 +2549,7 @@ static int hpsa_bmic_ctrl_mode_sense(struct ctlr_info *h, out: cmd_free(h, c); return rc; - } +} static int hpsa_send_reset(struct ctlr_info *h, unsigned char *scsi3addr, u8 reset_type, int reply_queue) @@ -2570,10 +2560,6 @@ static int hpsa_send_reset(struct ctlr_info *h, unsigned char *scsi3addr, c = cmd_alloc(h); - if (c == NULL) {/* trouble... */ - dev_warn(&h->pdev->dev, "cmd_alloc returned NULL!\n"); - return -ENOMEM; - } /* fill_cmd can't fail here, no data buffer to map. */ (void) fill_cmd(c, HPSA_DEVICE_RESET_MSG, h, NULL, 0, 0, @@ -2701,10 +2687,7 @@ static int hpsa_get_raid_map(struct ctlr_info *h, struct ErrorInfo *ei; c = cmd_alloc(h); - if (c == NULL) { - dev_warn(&h->pdev->dev, "cmd_alloc returned NULL!\n"); - return -ENOMEM; - } + if (fill_cmd(c, HPSA_GET_RAID_MAP, h, &this_device->raid_map, sizeof(this_device->raid_map), 0, scsi3addr, TYPE_CMD)) { @@ -2877,10 +2860,7 @@ static int hpsa_scsi_do_report_luns(struct ctlr_info *h, int logical, struct ErrorInfo *ei; c = cmd_alloc(h); - if (c == NULL) {/* trouble... */ - dev_err(&h->pdev->dev, "cmd_alloc returned NULL!\n"); - return -1; - } + /* address the controller */ memset(scsi3addr, 0, sizeof(scsi3addr)); if (fill_cmd(c, logical ? HPSA_REPORT_LOG : HPSA_REPORT_PHYS, h, @@ -2995,8 +2975,7 @@ static int hpsa_volume_offline(struct ctlr_info *h, #define ASCQ_LUN_NOT_READY_INITIALIZING_CMD_REQ 0x02 c = cmd_alloc(h); - if (!c) - return 0; + (void) fill_cmd(c, TEST_UNIT_READY, h, NULL, 0, 0, scsi3addr, TYPE_CMD); rc = hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE, NO_TIMEOUT); if (rc) { @@ -3070,8 +3049,7 @@ static int hpsa_device_supports_aborts(struct ctlr_info *h, return 1; c = cmd_alloc(h); - if (!c) - return -ENOMEM; + (void) fill_cmd(c, HPSA_ABORT_MSG, h, &tag, 0, 0, scsi3addr, TYPE_MSG); (void) hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE, NO_TIMEOUT); /* no unmap needed here because no data xfer. */ @@ -4642,10 +4620,7 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd) return 0; } c = cmd_alloc(h); - if (c == NULL) {/* trouble... */ - dev_err(&h->pdev->dev, "cmd_alloc returned NULL!\n"); - return SCSI_MLQUEUE_HOST_BUSY; - } + if (unlikely(lockup_detected(h))) { cmd->result = DID_NO_CONNECT << 16; cmd_free(h, c); @@ -4806,11 +4781,6 @@ static int wait_for_device_to_become_ready(struct ctlr_info *h, struct CommandList *c; c = cmd_alloc(h); - if (!c) { - dev_warn(&h->pdev->dev, "out of memory in " - "wait_for_device_to_become_ready.\n"); - return IO_ERROR; - } /* Send test unit ready until device ready, or give up. */ while (count < HPSA_TUR_RETRY_LIMIT) { @@ -4973,10 +4943,6 @@ static int hpsa_send_abort(struct ctlr_info *h, unsigned char *scsi3addr, __le32 tagupper, taglower; c = cmd_alloc(h); - if (c == NULL) {/* trouble... */ - dev_warn(&h->pdev->dev, "cmd_alloc returned N
[PATCH v3 13/42] hpsa: print accurate SSD Smart Path Enabled status
From: Robert Elliott offload_enabled changes are deferred until after the added/updated prints occur, so the values are incorrect. defer printing SSD Smart Path Enabled status information until the information is correct Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Robert Elliott Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 12 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 813f3c8..e9d3d71 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1090,12 +1090,12 @@ lun_assigned: h->dev[n] = device; h->ndevices++; - device->offload_to_be_enabled = device->offload_enabled; - device->offload_enabled = 0; added[*nadded] = device; (*nadded)++; hpsa_show_dev_msg(HPSA_INFO, h, device, device->expose_state & HPSA_SCSI_ADD ? "added" : "masked"); + device->offload_to_be_enabled = device->offload_enabled; + device->offload_enabled = 0; return 0; } @@ -1103,6 +1103,7 @@ lun_assigned: static void hpsa_scsi_update_entry(struct ctlr_info *h, int hostno, int entry, struct hpsa_scsi_dev_t *new_entry) { + int offload_enabled; /* assumes h->devlock is held */ BUG_ON(entry < 0 || entry >= HPSA_MAX_DEVICES); @@ -1135,7 +1136,10 @@ static void hpsa_scsi_update_entry(struct ctlr_info *h, int hostno, if (!new_entry->offload_enabled) h->dev[entry]->offload_enabled = 0; + offload_enabled = h->dev[entry]->offload_enabled; + h->dev[entry]->offload_enabled = h->dev[entry]->offload_to_be_enabled; hpsa_show_dev_msg(HPSA_INFO, h, h->dev[entry], "updated"); + h->dev[entry]->offload_enabled = offload_enabled; } /* Replace an entry from h->dev[] array. */ @@ -1158,12 +1162,12 @@ static void hpsa_scsi_replace_entry(struct ctlr_info *h, int hostno, new_entry->lun = h->dev[entry]->lun; } - new_entry->offload_to_be_enabled = new_entry->offload_enabled; - new_entry->offload_enabled = 0; h->dev[entry] = new_entry; added[*nadded] = new_entry; (*nadded)++; hpsa_show_dev_msg(HPSA_INFO, h, new_entry, "replaced"); + new_entry->offload_to_be_enabled = new_entry->offload_enabled; + new_entry->offload_enabled = 0; } /* Remove an entry from h->dev[] array. */ -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 24/42] hpsa: clean up some error reporting output in abort handler
From: Robert Elliott report more useful information on aborts Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Robert Elliott Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 29 ++--- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index f980b89..7ab34f8 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -5140,10 +5140,10 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc) return FAILED; memset(msg, 0, sizeof(msg)); - ml += sprintf(msg+ml, "scsi %d:%d:%d:%llu %s", + ml += sprintf(msg+ml, "scsi %d:%d:%d:%llu %s %p", h->scsi_host->host_no, sc->device->channel, sc->device->id, sc->device->lun, - "Aborting command"); + "Aborting command", sc); /* Find the device of the command to be aborted */ dev = sc->device->hostdata; @@ -5177,12 +5177,12 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc) ml += sprintf(msg+ml, "Tag:0x%08x:%08x ", tagupper, taglower); as = abort->scsi_cmd; if (as != NULL) - ml += sprintf(msg+ml, "Command:0x%x SN:0x%lx ", - as->cmnd[0], as->serial_number); - dev_dbg(&h->pdev->dev, "%s\n", msg); - dev_warn(&h->pdev->dev, "scsi %d:%d:%d:%d %s\n", - h->scsi_host->host_no, dev->bus, dev->target, dev->lun, - "Aborting command"); + ml += sprintf(msg+ml, + "CDBLen: %d CDB: 0x%02x%02x... SN: 0x%lx ", + as->cmd_len, as->cmnd[0], as->cmnd[1], + as->serial_number); + dev_warn(&h->pdev->dev, "%s BEING SENT\n", msg); + /* * Command is in flight, or possibly already completed * by the firmware (but not to the scsi mid layer) but we can't @@ -5190,7 +5190,8 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc) */ if (wait_for_available_abort_cmd(h)) { dev_warn(&h->pdev->dev, - "Timed out waiting for an abort command to become available.\n"); + "%s FAILED, timeout waiting for an abort command to become available.\n", + msg); cmd_free(h, abort); return FAILED; } @@ -5198,16 +5199,14 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc) atomic_inc(&h->abort_cmds_available); wake_up_all(&h->abort_cmd_wait_queue); if (rc != 0) { - dev_warn(&h->pdev->dev, "scsi %d:%d:%d:%d %s\n", - h->scsi_host->host_no, - dev->bus, dev->target, dev->lun, - "FAILED to abort command"); + dev_warn(&h->pdev->dev, "%s SENT, FAILED\n", msg); cmd_free(h, abort); return FAILED; } - dev_info(&h->pdev->dev, "%s REQUEST SUCCEEDED.\n", msg); + dev_info(&h->pdev->dev, "%s SENT, SUCCESS\n", msg); - /* If the abort(s) above completed and actually aborted the + /* +* If the abort(s) above completed and actually aborted the * command, then the command to be aborted should already be * completed. If not, wait around a bit more to see if they * manage to complete normally. -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 15/42] hpsa: Get queue depth from identify physical bmic for physical disks.
From: Joe Handzik get drive queue depth to help avoid task set full conditions. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Joe Handzik Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 33 + 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 76f9042..3fa72a1 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3497,29 +3497,22 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) ncurrent++; break; case TYPE_DISK: - if (h->hba_mode_enabled) { - /* never use raid mapper in HBA mode */ - this_device->offload_enabled = 0; - ncurrent++; - break; - } else if (h->acciopath_status) { - if (i >= nphysicals) { - ncurrent++; - break; - } - } else { - if (i < nphysicals) - break; + if (i >= nphysicals) { ncurrent++; break; } - if (h->transMethod & CFGTBL_Trans_io_accel1 || - h->transMethod & CFGTBL_Trans_io_accel2) { - hpsa_get_ioaccel_drive_info(h, this_device, - lunaddrbytes, id_phys); - atomic_set(&this_device->ioaccel_cmds_out, 0); - ncurrent++; - } + + if (h->hba_mode_enabled) + /* never use raid mapper in HBA mode */ + this_device->offload_enabled = 0; + else if (!(h->transMethod & CFGTBL_Trans_io_accel1 || + h->transMethod & CFGTBL_Trans_io_accel2)) + break; + + hpsa_get_ioaccel_drive_info(h, this_device, + lunaddrbytes, id_phys); + atomic_set(&this_device->ioaccel_cmds_out, 0); + ncurrent++; break; case TYPE_TAPE: case TYPE_MEDIUM_CHANGER: -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 32/42] hpsa: skip free_irq calls if irqs are not allocated
From: Robert Elliott If try_soft_reset fails to re-allocate irqs, the error exit starts with free_irq calls, which generate kernel WARN messages since they were already freed a few lines earlier. Jump to the next exit label to skip the free_irq calls. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Robert Elliott Signed-off-by: Don Brace --- drivers/scsi/hpsa.c |7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 33aca38..f26e6bc 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -7799,7 +7799,12 @@ reinit_after_soft_reset: if (rc) { dev_warn(&h->pdev->dev, "Failed to request_irq after soft reset.\n"); - goto clean4; + /* +* clean4 starts with free_irqs, but that was just +* done. Then, request_irqs_failed, so there is +* nothing to free. So, goto the next label. +*/ + goto clean3; } rc = hpsa_kdump_soft_reset(h); -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 18/42] hpsa: refactor freeing of resources into more logical functions
From: Robert Elliott refactor freeing of resources into more logical functions Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Robert Elliott Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 104 +++ 1 file changed, 56 insertions(+), 48 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 3559425a4..9ca86be 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -235,6 +235,8 @@ static void check_ioctl_unit_attention(struct ctlr_info *h, static void calc_bucket_map(int *bucket, int num_buckets, int nsgs, int min_blocks, u32 *bucket_map); static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h); +static void hpsa_free_ioaccel1_cmd_and_bft(struct ctlr_info *h); +static void hpsa_free_ioaccel2_cmd_and_bft(struct ctlr_info *h); static inline u32 next_command(struct ctlr_info *h, u8 q); static int hpsa_find_cfg_addrs(struct pci_dev *pdev, void __iomem *vaddr, u32 *cfg_base_addr, u64 *cfg_base_addr_index, @@ -6924,6 +6926,21 @@ out_disable: return rc; } +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_alloc_cmd_pool(struct ctlr_info *h) { h->cmd_pool_bits = kzalloc( @@ -6948,28 +6965,6 @@ clean_up: return -ENOMEM; } -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->ioaccel2_cmd_pool) - pci_free_consistent(h->pdev, - h->nr_cmds * sizeof(*h->ioaccel2_cmd_pool), - h->ioaccel2_cmd_pool, h->ioaccel2_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); - if (h->ioaccel_cmd_pool) - pci_free_consistent(h->pdev, - h->nr_cmds * sizeof(struct io_accel1_cmd), - h->ioaccel_cmd_pool, h->ioaccel_cmd_pool_dhandle); -} - static void hpsa_irq_affinity_hints(struct ctlr_info *h) { int i, cpu; @@ -7090,8 +7085,10 @@ static void hpsa_free_reply_queues(struct ctlr_info *h) for (i = 0; i < h->nreply_queues; i++) { if (!h->reply_queue[i].head) continue; - pci_free_consistent(h->pdev, h->reply_queue_size, - h->reply_queue[i].head, h->reply_queue[i].busaddr); + pci_free_consistent(h->pdev, + h->reply_queue_size, + h->reply_queue[i].head, + h->reply_queue[i].busaddr); h->reply_queue[i].head = NULL; h->reply_queue[i].busaddr = 0; } @@ -7102,9 +7099,10 @@ static void hpsa_undo_allocations_after_kdump_soft_reset(struct ctlr_info *h) hpsa_free_irqs(h); hpsa_free_sg_chain_blocks(h); hpsa_free_cmd_pool(h); - kfree(h->ioaccel1_blockFetchTable); - kfree(h->blockFetchTable); - hpsa_free_reply_queues(h); + kfree(h->blockFetchTable); /* perf 2 */ + hpsa_free_reply_queues(h); /* perf 1 */ + hpsa_free_ioaccel1_cmd_and_bft(h); /* perf 1 */ + hpsa_free_ioaccel2_cmd_and_bft(h); /* perf 1 */ hpsa_free_cfgtables(h); /* pci_init 4 */ iounmap(h->vaddr); /* pci_init 3 */ hpsa_disable_interrupt_mode(h); /* pci_init 2 */ @@ -7535,6 +7533,8 @@ reinit_after_soft_reset: clean4: hpsa_free_sg_chain_blocks(h); hpsa_free_cmd_pool(h); + hpsa_free_ioaccel1_cmd_and_bft(h); + hpsa_free_ioaccel2_cmd_and_bft(h); clean2_and_free_irqs: hpsa_free_irqs(h); clean2: @@ -7636,17 +7636,11 @@ static void hpsa_remove_one(struct pci_dev *pdev) hpsa_free_device_info(h); hpsa_free_sg_chain_blocks(h); - pci_free_consistent(h->pdev, - h->nr_cmds * sizeof(struct CommandList), - h->cmd_pool, h->cmd_pool_dhandle); - pci_free_consistent(h->pdev, - h->nr_
[PATCH v3 31/42] hpsa: call pci_release_regions after pci_disable_device
From: Robert Elliott Despite the fact that PCI devices are enabled in this order: 1. pci_enable_device 2. pci_request_regions Documentation/PCI/pci.txt specifies that they be undone in this order 1. pci_disable_device 2. pci_release_regions Tested by injecting error in the call to pci_enable_device in hpsa_init_one -> hpsa_pci_init: [9.095001] hpsa :04:00.0: failed to enable PCI device [9.095005] hpsa: probe of :04:00.0 failed with error -22 (-22 is -EINVAL) and then in the call pci_request_regions: [9.178623] hpsa :04:00.0: failed to obtain PCI resources [9.178671] hpsa: probe of :04:00.0 failed with error -16 (-16 is -EBUSY) and then by adding reset_devices to the kernel command line and inject errors into the two calls to pci_enable_device and the call to pci_request_regions in hpsa_init_one -> hpsa_init_reset_devices. (inject on 6th call, 1st to hpsa2) [ 62.413750] hpsa :04:00.0: Failed to enable PCI device (inject on 7th call, 2nd to hpsa2) [ 62.807571] hpsa :04:00.0: failed to enable device. (inject on 8th call, 3rd to hpsa2) [ 62.697198] hpsa :04:00.0: failed to obtain PCI resources [ 62.697234] hpsa: probe of :04:00.0 failed with error -16 The reset_devices path calls return -ENODEV on failure rather than passing the result, which apparently doesn't cause the pci driver to print anything. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Robert Elliott Signed-off-by: Don Brace < don.br...@pmcs.com> --- drivers/scsi/hpsa.c | 17 + 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index b533b8e..33aca38 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -7075,8 +7075,12 @@ static void hpsa_free_pci_init(struct ctlr_info *h) iounmap(h->vaddr); /* pci_init 3 */ h->vaddr = NULL; hpsa_disable_interrupt_mode(h); /* pci_init 2 */ - pci_release_regions(h->pdev); /* pci_init 2 */ + /* +* call pci_disable_device before pci_release_regions per +* Documentation/PCI/pci.txt +*/ pci_disable_device(h->pdev);/* pci_init 1 */ + pci_release_regions(h->pdev); /* pci_init 2 */ } /* several items must be freed later */ @@ -7099,6 +7103,7 @@ static int hpsa_pci_init(struct ctlr_info *h) err = pci_enable_device(h->pdev); if (err) { dev_err(&h->pdev->dev, "failed to enable PCI device\n"); + pci_disable_device(h->pdev); return err; } @@ -7106,7 +7111,8 @@ static int hpsa_pci_init(struct ctlr_info *h) if (err) { dev_err(&h->pdev->dev, "failed to obtain PCI resources\n"); - goto clean1;/* pci */ + pci_disable_device(h->pdev); + return err; } pci_set_master(h->pdev); @@ -7147,9 +7153,12 @@ clean3: /* vaddr, intmode+region, pci */ h->vaddr = NULL; clean2:/* intmode+region, pci */ hpsa_disable_interrupt_mode(h); - pci_release_regions(h->pdev); -clean1:/* pci */ + /* +* call pci_disable_device before pci_release_regions per +* Documentation/PCI/pci.txt +*/ pci_disable_device(h->pdev); + pci_release_regions(h->pdev); return err; } -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 16/42] hpsa: break hpsa_free_irqs_and_disable_msix into two functions
From: Robert Elliott replace calls to hpsa_free_irqs_and_disable_msix with hpsa_free_irqs and hpsa_disable_interrupt_mode Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Robert Elliott Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 35 ++- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 3fa72a1..c98c591 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -6402,10 +6402,20 @@ static int find_PCI_BAR_index(struct pci_dev *pdev, unsigned long pci_bar_addr) return -1; } +static void hpsa_disable_interrupt_mode(struct ctlr_info *h) +{ + if (h->msix_vector) { + if (h->pdev->msix_enabled) + pci_disable_msix(h->pdev); + } else if (h->msi_vector) { + if (h->pdev->msi_enabled) + pci_disable_msi(h->pdev); + } +} + /* If MSI/MSI-X is supported by the kernel we will try to enable it on * controllers that are capable. If not, we use legacy INTx mode. */ - static void hpsa_interrupt_mode(struct ctlr_info *h) { #ifdef CONFIG_PCI_MSI @@ -7046,20 +7056,6 @@ static int hpsa_kdump_soft_reset(struct ctlr_info *h) return 0; } -static void hpsa_free_irqs_and_disable_msix(struct ctlr_info *h) -{ - hpsa_free_irqs(h); -#ifdef CONFIG_PCI_MSI - if (h->msix_vector) { - if (h->pdev->msix_enabled) - pci_disable_msix(h->pdev); - } else if (h->msi_vector) { - if (h->pdev->msi_enabled) - pci_disable_msi(h->pdev); - } -#endif /* CONFIG_PCI_MSI */ -} - static void hpsa_free_reply_queues(struct ctlr_info *h) { int i; @@ -7076,7 +7072,7 @@ static void hpsa_free_reply_queues(struct ctlr_info *h) static void hpsa_undo_allocations_after_kdump_soft_reset(struct ctlr_info *h) { - hpsa_free_irqs_and_disable_msix(h); + hpsa_free_irqs(h); hpsa_free_sg_chain_blocks(h); hpsa_free_cmd_pool(h); kfree(h->ioaccel1_blockFetchTable); @@ -7088,6 +7084,7 @@ static void hpsa_undo_allocations_after_kdump_soft_reset(struct ctlr_info *h) iounmap(h->transtable); if (h->cfgtable) iounmap(h->cfgtable); + hpsa_disable_interrupt_mode(h); pci_disable_device(h->pdev); pci_release_regions(h->pdev); kfree(h); @@ -7576,7 +7573,8 @@ static void hpsa_shutdown(struct pci_dev *pdev) */ hpsa_flush_cache(h); h->access.set_intr_mask(h, HPSA_INTR_OFF); - hpsa_free_irqs_and_disable_msix(h); + hpsa_free_irqs(h); + hpsa_disable_interrupt_mode(h); /* pci_init 2 */ } static void hpsa_free_device_info(struct ctlr_info *h) @@ -7607,7 +7605,10 @@ static void hpsa_remove_one(struct pci_dev *pdev) destroy_workqueue(h->rescan_ctlr_wq); destroy_workqueue(h->resubmit_wq); hpsa_unregister_scsi(h);/* unhook from SCSI subsystem */ + + /* includes hpsa_free_irqs and hpsa_disable_interrupt_mode */ hpsa_shutdown(pdev); + iounmap(h->vaddr); iounmap(h->transtable); iounmap(h->cfgtable); -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 25/42] hpsa: do not print ioaccel2 warning messages about unusual completions.
From: Robert Elliott The SCSI midlayer already prints more detail about completions, and has logging level options to filter them if not wanted. These just slow down the system if a lot of errors occur, stressing error handling even more. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Robert Elliott Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 24 1 file changed, 24 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 7ab34f8..7d0e226 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1906,9 +1906,6 @@ static int handle_ioaccel_mode2_error(struct ctlr_info *h, case IOACCEL2_STATUS_SR_TASK_COMP_GOOD: break; case IOACCEL2_STATUS_SR_TASK_COMP_CHK_COND: - dev_warn(&h->pdev->dev, - "%s: task complete with check condition.\n", - "HP SSD Smart Path"); cmd->result |= SAM_STAT_CHECK_CONDITION; if (c2->error_data.data_present != IOACCEL2_SENSE_DATA_PRESENT) { @@ -1928,30 +1925,18 @@ static int handle_ioaccel_mode2_error(struct ctlr_info *h, retry = 1; break; case IOACCEL2_STATUS_SR_TASK_COMP_BUSY: - dev_warn(&h->pdev->dev, - "%s: task complete with BUSY status.\n", - "HP SSD Smart Path"); retry = 1; break; case IOACCEL2_STATUS_SR_TASK_COMP_RES_CON: - dev_warn(&h->pdev->dev, - "%s: task complete with reservation conflict.\n", - "HP SSD Smart Path"); retry = 1; break; case IOACCEL2_STATUS_SR_TASK_COMP_SET_FULL: retry = 1; break; case IOACCEL2_STATUS_SR_TASK_COMP_ABORTED: - dev_warn(&h->pdev->dev, - "%s: task complete with aborted status.\n", - "HP SSD Smart Path"); retry = 1; break; default: - dev_warn(&h->pdev->dev, - "%s: task complete with unrecognized status: 0x%02x\n", - "HP SSD Smart Path", c2->error_data.status); retry = 1; break; } @@ -1980,9 +1965,6 @@ static int handle_ioaccel_mode2_error(struct ctlr_info *h, break; default: retry = 1; - dev_warn(&h->pdev->dev, - "unexpected delivery or target failure, status = 0x%02x\n", - c2->error_data.status); } break; case IOACCEL2_SERV_RESPONSE_TMF_COMPLETE: @@ -1990,17 +1972,11 @@ static int handle_ioaccel_mode2_error(struct ctlr_info *h, case IOACCEL2_SERV_RESPONSE_TMF_SUCCESS: break; case IOACCEL2_SERV_RESPONSE_TMF_REJECTED: - dev_warn(&h->pdev->dev, "task management function rejected.\n"); retry = 1; break; case IOACCEL2_SERV_RESPONSE_TMF_WRONG_LUN: - dev_warn(&h->pdev->dev, "task management function invalid LUN\n"); break; default: - dev_warn(&h->pdev->dev, - "%s: Unrecognized server response: 0x%02x\n", - "HP SSD Smart Path", - c2->error_data.serv_response); retry = 1; break; } -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 11/42] hpsa: try resubmitting down raid path on task set full
From: Stephen Cameron allow the controller firmware to queue up commands when the ioaccel device queue is full. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/hpsa.c |3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 15bf3bcb..76865df 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1855,8 +1855,7 @@ static int handle_ioaccel_mode2_error(struct ctlr_info *h, retry = 1; break; case IOACCEL2_STATUS_SR_TASK_COMP_SET_FULL: - /* Make scsi midlayer do unlimited retries */ - cmd->result = DID_IMM_RETRY << 16; + retry = 1; break; case IOACCEL2_STATUS_SR_TASK_COMP_ABORTED: dev_warn(&h->pdev->dev, -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 12/42] hpsa: factor out hpsa_ioaccel_submit function
From: Webb Scales clean up command submission Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Webb Scales Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 91 +-- 1 file changed, 66 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 76865df..813f3c8 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -4408,6 +4408,33 @@ static inline void hpsa_cmd_partial_init(struct ctlr_info *h, int index, c->busaddr = (u32) cmd_dma_handle; } +static int hpsa_ioaccel_submit(struct ctlr_info *h, + struct CommandList *c, struct scsi_cmnd *cmd, + unsigned char *scsi3addr) +{ + struct hpsa_scsi_dev_t *dev = cmd->device->hostdata; + int rc = IO_ACCEL_INELIGIBLE; + + cmd->host_scribble = (unsigned char *) c; + + if (dev->offload_enabled) { + hpsa_cmd_init(h, c->cmdindex, c); + c->cmd_type = CMD_SCSI; + c->scsi_cmd = cmd; + rc = hpsa_scsi_ioaccel_raid_map(h, c); + if (rc < 0) /* scsi_dma_map failed. */ + rc = SCSI_MLQUEUE_HOST_BUSY; + } else if (dev->ioaccel_handle) { + hpsa_cmd_init(h, c->cmdindex, c); + c->cmd_type = CMD_SCSI; + c->scsi_cmd = cmd; + rc = hpsa_scsi_ioaccel_direct_map(h, c); + if (rc < 0) /* scsi_dma_map failed. */ + rc = SCSI_MLQUEUE_HOST_BUSY; + } + return rc; +} + static void hpsa_command_resubmit_worker(struct work_struct *work) { struct scsi_cmnd *cmd; @@ -4419,15 +4446,46 @@ static void hpsa_command_resubmit_worker(struct work_struct *work) dev = cmd->device->hostdata; if (!dev) { cmd->result = DID_NO_CONNECT << 16; + cmd_free(c->h, c); cmd->scsi_done(cmd); return; } + if (c->cmd_type == CMD_IOACCEL2) { + struct ctlr_info *h = c->h; + struct io_accel2_cmd *c2 = &h->ioaccel2_cmd_pool[c->cmdindex]; + int rc; + + if (c2->error_data.serv_response == + IOACCEL2_STATUS_SR_TASK_COMP_SET_FULL) { + rc = hpsa_ioaccel_submit(h, c, cmd, dev->scsi3addr); + if (rc == 0) + return; + if (rc == SCSI_MLQUEUE_HOST_BUSY) { + /* +* If we get here, it means dma mapping failed. +* Try again via scsi mid layer, which will +* then get SCSI_MLQUEUE_HOST_BUSY. +*/ + cmd->result = DID_IMM_RETRY << 16; + cmd->scsi_done(cmd); + cmd_free(h, c); /* FIX-ME: on merge, change +* to cmd_tagged_free() and +* ultimately to +* hpsa_cmd_free_and_done(). */ + return; + } + /* else, fall thru and resubmit down CISS path */ + } + } hpsa_cmd_partial_init(c->h, c->cmdindex, c); if (hpsa_ciss_submit(c->h, c, cmd, dev->scsi3addr)) { /* * If we get here, it means dma mapping failed. Try * again via scsi mid layer, which will then get * SCSI_MLQUEUE_HOST_BUSY. +* +* hpsa_ciss_submit will have already freed c +* if it encountered a dma mapping failure. */ cmd->result = DID_IMM_RETRY << 16; cmd->scsi_done(cmd); @@ -4477,31 +4535,14 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd) if (likely(cmd->retries == 0 && cmd->request->cmd_type == REQ_TYPE_FS && h->acciopath_status)) { - - cmd->host_scribble = (unsigned char *) c; - - if (dev->offload_enabled) { - hpsa_cmd_init(h, c->cmdindex, c); - c->cmd_type = CMD_SCSI; - c->scsi_cmd = cmd; - rc = hpsa_scsi_ioaccel_raid_map(h, c); - if (rc == 0) - return 0; /* Sent on ioaccel path */ - if (rc < 0) { /* scsi_dma_map failed. */ - cmd_free(h, c); - return SCSI_MLQUEUE_HOST_BUSY; - } - } else if (dev->ioaccel_handle) { - hpsa_cmd_init(h, c->cmdindex, c); - c->cmd_type = CMD_SCSI; -
[PATCH v3 19/42] hpsa: add ioaccel sg chaining for the ioaccel2 path
From: Webb Scales Increase the request size for ioaccel2 path. The error, if any, returned by hpsa_allocate_ioaccel2_sg_chain_blocks to hpsa_alloc_ioaccel2_cmd_and_bft should be returned upstream rather than assumed to be -ENOMEM. This differs slightly from hpsa_alloc_ioaccel1_cmd_and_bft, which does not call another hpsa_allocate function and only has -ENOMEM to return from some kmalloc calls. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Robert Elliott Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 125 +++ drivers/scsi/hpsa.h |1 2 files changed, 116 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 9ca86be..0a3ea37 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1734,6 +1734,46 @@ static void hpsa_slave_destroy(struct scsi_device *sdev) /* nothing to do. */ } +static void hpsa_free_ioaccel2_sg_chain_blocks(struct ctlr_info *h) +{ + int i; + + if (!h->ioaccel2_cmd_sg_list) + return; + for (i = 0; i < h->nr_cmds; i++) { + kfree(h->ioaccel2_cmd_sg_list[i]); + h->ioaccel2_cmd_sg_list[i] = NULL; + } + kfree(h->ioaccel2_cmd_sg_list); + h->ioaccel2_cmd_sg_list = NULL; +} + +static int hpsa_allocate_ioaccel2_sg_chain_blocks(struct ctlr_info *h) +{ + int i; + + if (h->chainsize <= 0) + return 0; + + h->ioaccel2_cmd_sg_list = + kzalloc(sizeof(*h->ioaccel2_cmd_sg_list) * h->nr_cmds, + GFP_KERNEL); + if (!h->ioaccel2_cmd_sg_list) + return -ENOMEM; + for (i = 0; i < h->nr_cmds; i++) { + h->ioaccel2_cmd_sg_list[i] = + kmalloc(sizeof(*h->ioaccel2_cmd_sg_list[i]) * + h->maxsgentries, GFP_KERNEL); + if (!h->ioaccel2_cmd_sg_list[i]) + goto clean; + } + return 0; + +clean: + hpsa_free_ioaccel2_sg_chain_blocks(h); + return -ENOMEM; +} + static void hpsa_free_sg_chain_blocks(struct ctlr_info *h) { int i; @@ -1776,6 +1816,39 @@ clean: return -ENOMEM; } +static int hpsa_map_ioaccel2_sg_chain_block(struct ctlr_info *h, + struct io_accel2_cmd *cp, struct CommandList *c) +{ + struct ioaccel2_sg_element *chain_block; + u64 temp64; + u32 chain_size; + + chain_block = h->ioaccel2_cmd_sg_list[c->cmdindex]; + chain_size = le32_to_cpu(cp->data_len); + temp64 = pci_map_single(h->pdev, chain_block, chain_size, + PCI_DMA_TODEVICE); + if (dma_mapping_error(&h->pdev->dev, temp64)) { + /* prevent subsequent unmapping */ + cp->sg->address = 0; + return -1; + } + cp->sg->address = cpu_to_le64(temp64); + return 0; +} + +static void hpsa_unmap_ioaccel2_sg_chain_block(struct ctlr_info *h, + struct io_accel2_cmd *cp) +{ + struct ioaccel2_sg_element *chain_sg; + u64 temp64; + u32 chain_size; + + chain_sg = cp->sg; + temp64 = le64_to_cpu(chain_sg->address); + chain_size = le32_to_cpu(cp->data_len); + pci_unmap_single(h->pdev, temp64, chain_size, PCI_DMA_TODEVICE); +} + static int hpsa_map_sg_chain_block(struct ctlr_info *h, struct CommandList *c) { @@ -1985,6 +2058,7 @@ static void complete_scsi_command(struct CommandList *cp) struct ctlr_info *h; struct ErrorInfo *ei; struct hpsa_scsi_dev_t *dev; + struct io_accel2_cmd *c2; int sense_key; int asc; /* additional sense code */ @@ -1995,12 +2069,17 @@ static void complete_scsi_command(struct CommandList *cp) cmd = cp->scsi_cmd; h = cp->h; dev = cmd->device->hostdata; + c2 = &h->ioaccel2_cmd_pool[cp->cmdindex]; scsi_dma_unmap(cmd); /* undo the DMA mappings */ if ((cp->cmd_type == CMD_SCSI) && (le16_to_cpu(cp->Header.SGTotal) > h->max_cmd_sg_entries)) hpsa_unmap_sg_chain_block(h, cp); + if ((cp->cmd_type == CMD_IOACCEL2) && + (c2->sg[0].chain_indicator == IOACCEL2_CHAIN)) + hpsa_unmap_ioaccel2_sg_chain_block(h, c2); + cmd->result = (DID_OK << 16); /* host byte */ cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */ @@ -3842,10 +3921,7 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h, u32 len; u32 total_len = 0; - if (scsi_sg_count(cmd) > h->ioaccel_maxsg) { - atomic_dec(&phys_disk->ioaccel_cmds_out); - return IO_ACCEL_INELIGIBLE; - } + BUG_ON(scsi_sg_count(cmd) > h->maxsgentries); if (fixup_ioaccel_cdb(cdb, &cdb_len)) { atomic_dec(&phys_disk->ioaccel_cmds_out); @@ -3868,8 +3944,19 @@ static int hpsa_scsi_ioaccel2_qu
[PATCH v3 30/42] hpsa: performance tweak for hpsa_scatter_gather()
From: Webb Scales Divide the loop in hpsa_scatter_gather() into two, one for the initial SG list and a second one for the chained list, if any. This allows the conditional check which resets the indicies for the chained list to be performed outside the loop instead of being done on every iteration inside the loop. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Webb Scales Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 39 --- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 3751df3..b533b8e 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3709,7 +3709,7 @@ static int hpsa_scatter_gather(struct ctlr_info *h, struct scsi_cmnd *cmd) { struct scatterlist *sg; - int use_sg, i, sg_index, chained; + int use_sg, i, sg_limit, chained, last_sg; struct SGDescriptor *curr_sg; BUG_ON(scsi_sg_count(cmd) > h->maxsgentries); @@ -3721,22 +3721,39 @@ static int hpsa_scatter_gather(struct ctlr_info *h, if (!use_sg) goto sglist_finished; + /* +* If the number of entries is greater than the max for a single list, +* then we have a chained list; we will set up all but one entry in the +* first list (the last entry is saved for link information); +* otherwise, we don't have a chained list and we'll set up at each of +* the entries in the one list. +*/ curr_sg = cp->SG; - chained = 0; - sg_index = 0; - scsi_for_each_sg(cmd, sg, use_sg, i) { - if (i == h->max_cmd_sg_entries - 1 && - use_sg > h->max_cmd_sg_entries) { - chained = 1; - curr_sg = h->cmd_sg_list[cp->cmdindex]; - sg_index = 0; - } + chained = use_sg > h->max_cmd_sg_entries; + sg_limit = chained ? h->max_cmd_sg_entries - 1 : use_sg; + last_sg = scsi_sg_count(cmd) - 1; + scsi_for_each_sg(cmd, sg, sg_limit, i) { hpsa_set_sg_descriptor(curr_sg, sg); curr_sg++; } + if (chained) { + /* +* Continue with the chained list. Set curr_sg to the chained +* list. Modify the limit to the total count less the entries +* we've already set up. Resume the scan at the list entry +* where the previous loop left off. +*/ + curr_sg = h->cmd_sg_list[cp->cmdindex]; + sg_limit = use_sg - sg_limit; + for_each_sg(sg, sg, sg_limit, i) { + hpsa_set_sg_descriptor(curr_sg, sg); + curr_sg++; + } + } + /* Back the pointer up to the last entry and mark it as "last". */ - (--curr_sg)->Ext = cpu_to_le32(HPSA_SG_LAST); + (curr_sg - 1)->Ext = cpu_to_le32(HPSA_SG_LAST); if (use_sg + chained > h->maxSG) h->maxSG = use_sg + chained; -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 23/42] hpsa: clean up driver init
From: Robert Elliott Improve initialization error handling in hpsa_init_one Clean up style and indent issues Rename functions for consistency Improve error messaging on allocations Fix return status from hpsa_put_ctlr_into_performant_mode Correct free order in hpsa_init_one using new function hpsa_free_performant_mode Prevent inadvertent use of null pointers by nulling out the parent structures and zeroing out associated size variables. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Robert Elliott Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 243 +-- 1 file changed, 157 insertions(+), 86 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 2cb4db7..f980b89 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -234,9 +234,8 @@ static void check_ioctl_unit_attention(struct ctlr_info *h, /* performant mode helper functions */ static void calc_bucket_map(int *bucket, int num_buckets, int nsgs, int min_blocks, u32 *bucket_map); -static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h); -static void hpsa_free_ioaccel1_cmd_and_bft(struct ctlr_info *h); -static void hpsa_free_ioaccel2_cmd_and_bft(struct ctlr_info *h); +static void hpsa_free_performant_mode(struct ctlr_info *h); +static int hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h); static inline u32 next_command(struct ctlr_info *h, u8 q); static int hpsa_find_cfg_addrs(struct pci_dev *pdev, void __iomem *vaddr, u32 *cfg_base_addr, u64 *cfg_base_addr_index, @@ -1665,6 +1664,7 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno, * since it didn't get added to scsi mid layer */ fixup_botched_add(h, added[i]); + added[i] = NULL; } free_and_out: @@ -1788,7 +1788,7 @@ static void hpsa_free_sg_chain_blocks(struct ctlr_info *h) h->cmd_sg_list = NULL; } -static int hpsa_allocate_sg_chain_blocks(struct ctlr_info *h) +static int hpsa_alloc_sg_chain_blocks(struct ctlr_info *h) { int i; @@ -6488,9 +6488,11 @@ static void hpsa_disable_interrupt_mode(struct ctlr_info *h) if (h->msix_vector) { if (h->pdev->msix_enabled) pci_disable_msix(h->pdev); + h->msix_vector = 0; } else if (h->msi_vector) { if (h->pdev->msi_enabled) pci_disable_msi(h->pdev); + h->msi_vector = 0; } } @@ -6629,10 +6631,14 @@ static int hpsa_find_cfg_addrs(struct pci_dev *pdev, void __iomem *vaddr, static void hpsa_free_cfgtables(struct ctlr_info *h) { - if (h->transtable) + if (h->transtable) { iounmap(h->transtable); - if (h->cfgtable) + h->transtable = NULL; + } + if (h->cfgtable) { iounmap(h->cfgtable); + h->cfgtable = NULL; + } } /* Find and map CISS config table and transfer table @@ -6849,6 +6855,7 @@ static void hpsa_free_pci_init(struct ctlr_info *h) { hpsa_free_cfgtables(h); /* pci_init 4 */ iounmap(h->vaddr); /* pci_init 3 */ + h->vaddr = NULL; hpsa_disable_interrupt_mode(h); /* pci_init 2 */ pci_release_regions(h->pdev); /* pci_init 2 */ pci_disable_device(h->pdev);/* pci_init 1 */ @@ -6919,6 +6926,7 @@ clean4: /* cfgtables, vaddr, intmode+region, pci */ hpsa_free_cfgtables(h); clean3:/* vaddr, intmode+region, pci */ iounmap(h->vaddr); + h->vaddr = NULL; clean2:/* intmode+region, pci */ hpsa_disable_interrupt_mode(h); pci_release_regions(h->pdev); @@ -7008,16 +7016,23 @@ out_disable: static void hpsa_free_cmd_pool(struct ctlr_info *h) { kfree(h->cmd_pool_bits); - if (h->cmd_pool) + h->cmd_pool_bits = NULL; + 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) + h->cmd_pool = NULL; + h->cmd_pool_dhandle = 0; + } + if (h->errinfo_pool) { pci_free_consistent(h->pdev, h->nr_cmds * sizeof(struct ErrorInfo), h->errinfo_pool, h->errinfo_pool_dhandle); + h->errinfo_pool = NULL; + h->errinfo_pool_dhandle = 0; + } } static int hpsa_alloc_cmd_pool(struct ctlr_info *h) @@ -7065,12 +7080,14 @@ static void hpsa_free_irqs(struct ctlr_info *h) i = h->intr_mode; irq_set_affinity_hint(h->intr[i], NULL); free_irq(h->intr[i], &h->q[i]); +
[PATCH v3 17/42] hpsa: clean up error handling
From: Robert Elliott refactor error cleanup and shutdown disable interrupts and pci_disable_device on critical failures add hpsa_free_cfgtables function Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Robert Elliott Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 92 --- 1 file changed, 58 insertions(+), 34 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index c98c591..3559425a4 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -6546,6 +6546,17 @@ static int hpsa_find_cfg_addrs(struct pci_dev *pdev, void __iomem *vaddr, return 0; } +static void hpsa_free_cfgtables(struct ctlr_info *h) +{ + if (h->transtable) + iounmap(h->transtable); + if (h->cfgtable) + iounmap(h->cfgtable); +} + +/* Find and map CISS config table and transfer table ++ * several items must be unmapped (freed) later ++ * */ static int hpsa_find_cfgtables(struct ctlr_info *h) { u64 cfg_offset; @@ -6572,8 +6583,11 @@ static int hpsa_find_cfgtables(struct ctlr_info *h) h->transtable = remap_pci_mem(pci_resource_start(h->pdev, cfg_base_addr_index)+cfg_offset+trans_offset, sizeof(*h->transtable)); - if (!h->transtable) + if (!h->transtable) { + dev_err(&h->pdev->dev, "Failed mapping transfer table\n"); + hpsa_free_cfgtables(h); return -ENOMEM; + } return 0; } @@ -6749,6 +6763,17 @@ error: return -ENODEV; } +/* free items allocated or mapped by hpsa_pci_init */ +static void hpsa_free_pci_init(struct ctlr_info *h) +{ + hpsa_free_cfgtables(h); /* pci_init 4 */ + iounmap(h->vaddr); /* pci_init 3 */ + hpsa_disable_interrupt_mode(h); /* pci_init 2 */ + pci_release_regions(h->pdev); /* pci_init 2 */ + pci_disable_device(h->pdev);/* pci_init 1 */ +} + +/* several items must be freed later */ static int hpsa_pci_init(struct ctlr_info *h) { int prod_index, err; @@ -6767,15 +6792,15 @@ static int hpsa_pci_init(struct ctlr_info *h) err = pci_enable_device(h->pdev); if (err) { - dev_warn(&h->pdev->dev, "unable to enable PCI device\n"); + dev_err(&h->pdev->dev, "failed to enable PCI device\n"); return err; } err = pci_request_regions(h->pdev, HPSA); if (err) { dev_err(&h->pdev->dev, - "cannot obtain PCI resources, aborting\n"); - return err; + "failed to obtain PCI resources\n"); + goto clean1;/* pci */ } pci_set_master(h->pdev); @@ -6783,40 +6808,41 @@ static int hpsa_pci_init(struct ctlr_info *h) hpsa_interrupt_mode(h); err = hpsa_pci_find_memory_BAR(h->pdev, &h->paddr); if (err) - goto err_out_free_res; + goto clean2;/* intmode+region, pci */ h->vaddr = remap_pci_mem(h->paddr, 0x250); if (!h->vaddr) { + dev_err(&h->pdev->dev, "failed to remap PCI mem\n"); err = -ENOMEM; - goto err_out_free_res; + goto clean2;/* intmode+region, pci */ } err = hpsa_wait_for_board_state(h->pdev, h->vaddr, BOARD_READY); if (err) - goto err_out_free_res; + goto clean3;/* vaddr, intmode+region, pci */ err = hpsa_find_cfgtables(h); if (err) - goto err_out_free_res; + goto clean3;/* vaddr, intmode+region, pci */ hpsa_find_board_params(h); if (!hpsa_CISS_signature_present(h)) { err = -ENODEV; - goto err_out_free_res; + goto clean4;/* cfgtables, vaddr, intmode+region, pci */ } hpsa_set_driver_support_bits(h); hpsa_p600_dma_prefetch_quirk(h); err = hpsa_enter_simple_mode(h); if (err) - goto err_out_free_res; + goto clean4;/* cfgtables, vaddr, intmode+region, pci */ return 0; -err_out_free_res: - if (h->transtable) - iounmap(h->transtable); - if (h->cfgtable) - iounmap(h->cfgtable); - if (h->vaddr) - iounmap(h->vaddr); - pci_disable_device(h->pdev); +clean4:/* cfgtables, vaddr, intmode+region, pci */ + hpsa_free_cfgtables(h); +clean3:/* vaddr, intmode+region, pci */ + iounmap(h->vaddr); +clean2:/* intmode+region, pci */ + hpsa_disable_interrupt_mode(h); pci_release_regions(h->pdev); +clean1:/* pci */ + pci_disable_device(h->pdev); return err; } @@ -7025,8 +7051,9 @@ static int hpsa_request_irqs(struct ctlr_info *h, } }
[PATCH v3 20/42] hpsa: add more ioaccel2 error handling, including underrun statuses.
From: Joe Handzik improve ioaccel2 error handling, including better handling of underrun statuses Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Joe Handzik Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 33 - drivers/scsi/hpsa_cmd.h |6 ++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 0a3ea37..ba89375a 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1898,6 +1898,7 @@ static int handle_ioaccel_mode2_error(struct ctlr_info *h, { int data_len; int retry = 0; + u32 ioaccel2_resid = 0; switch (c2->error_data.serv_response) { case IOACCEL2_SERV_RESPONSE_COMPLETE: @@ -1956,11 +1957,33 @@ static int handle_ioaccel_mode2_error(struct ctlr_info *h, } break; case IOACCEL2_SERV_RESPONSE_FAILURE: - /* don't expect to get here. */ - dev_warn(&h->pdev->dev, - "unexpected delivery or target failure, status = 0x%02x\n", - c2->error_data.status); - retry = 1; + switch (c2->error_data.status) { + case IOACCEL2_STATUS_SR_IO_ERROR: + case IOACCEL2_STATUS_SR_IO_ABORTED: + case IOACCEL2_STATUS_SR_OVERRUN: + retry = 1; + break; + case IOACCEL2_STATUS_SR_UNDERRUN: + cmd->result = (DID_OK << 16); /* host byte */ + cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */ + ioaccel2_resid = c2->error_data.resid_cnt[3] << 24; + ioaccel2_resid |= c2->error_data.resid_cnt[2] << 16; + ioaccel2_resid |= c2->error_data.resid_cnt[1] << 8; + ioaccel2_resid |= c2->error_data.resid_cnt[0]; + scsi_set_resid(cmd, ioaccel2_resid); + break; + case IOACCEL2_STATUS_SR_NO_PATH_TO_DEVICE: + case IOACCEL2_STATUS_SR_INVALID_DEVICE: + case IOACCEL2_STATUS_SR_IOACCEL_DISABLED: + /* We will get an event from ctlr to trigger rescan */ + retry = 1; + break; + default: + retry = 1; + dev_warn(&h->pdev->dev, + "unexpected delivery or target failure, status = 0x%02x\n", + c2->error_data.status); + } break; case IOACCEL2_SERV_RESPONSE_TMF_COMPLETE: break; diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h index 0efb6f2b..cecb62b 100644 --- a/drivers/scsi/hpsa_cmd.h +++ b/drivers/scsi/hpsa_cmd.h @@ -532,6 +532,12 @@ struct io_accel2_scsi_response { #define IOACCEL2_STATUS_SR_TASK_COMP_SET_FULL 0x28 #define IOACCEL2_STATUS_SR_TASK_COMP_ABORTED 0x40 #define IOACCEL2_STATUS_SR_IOACCEL_DISABLED0x0E +#define IOACCEL2_STATUS_SR_IO_ERROR0x01 +#define IOACCEL2_STATUS_SR_IO_ABORTED 0x02 +#define IOACCEL2_STATUS_SR_NO_PATH_TO_DEVICE 0x03 +#define IOACCEL2_STATUS_SR_INVALID_DEVICE 0x04 +#define IOACCEL2_STATUS_SR_UNDERRUN0x51 +#define IOACCEL2_STATUS_SR_OVERRUN 0x75 u8 data_present;/* low 2 bits */ #define IOACCEL2_NO_DATAPRESENT0x000 #define IOACCEL2_RESPONSE_DATAPRESENT 0x001 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 27/42] hpsa: use helper routines for finishing commands
From: Webb Scales cleanup command completions Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Webb Scales Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 78 --- 1 file changed, 31 insertions(+), 47 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index e9642dd..b0949f7 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -2010,6 +2010,19 @@ static int handle_ioaccel_mode2_error(struct ctlr_info *h, return retry; /* retry on raid path? */ } +static void hpsa_cmd_free_and_done(struct ctlr_info *h, + struct CommandList *c, struct scsi_cmnd *cmd) +{ + cmd_free(h, c); + cmd->scsi_done(cmd); +} + +static void hpsa_retry_cmd(struct ctlr_info *h, struct CommandList *c) +{ + INIT_WORK(&c->work, hpsa_command_resubmit_worker); + queue_work_on(raw_smp_processor_id(), h->resubmit_wq, &c->work); +} + static void process_ioaccel2_completion(struct ctlr_info *h, struct CommandList *c, struct scsi_cmnd *cmd, struct hpsa_scsi_dev_t *dev) @@ -2018,13 +2031,11 @@ static void process_ioaccel2_completion(struct ctlr_info *h, /* check for good status */ if (likely(c2->error_data.serv_response == 0 && - c2->error_data.status == 0)) { - cmd_free(h, c); - cmd->scsi_done(cmd); - return; - } + c2->error_data.status == 0)) + return hpsa_cmd_free_and_done(h, c, cmd); - /* Any RAID offload error results in retry which will use + /* +* Any RAID offload error results in retry which will use * the normal I/O path so the controller can handle whatever's * wrong. */ @@ -2034,19 +2045,14 @@ static void process_ioaccel2_completion(struct ctlr_info *h, if (c2->error_data.status == IOACCEL2_STATUS_SR_IOACCEL_DISABLED) dev->offload_enabled = 0; - goto retry_cmd; + + return hpsa_retry_cmd(h, c); } if (handle_ioaccel_mode2_error(h, c, cmd, c2)) - goto retry_cmd; - - cmd_free(h, c); - cmd->scsi_done(cmd); - return; + return hpsa_retry_cmd(h, c); -retry_cmd: - INIT_WORK(&c->work, hpsa_command_resubmit_worker); - queue_work_on(raw_smp_processor_id(), h->resubmit_wq, &c->work); + return hpsa_cmd_free_and_done(h, c, cmd); } /* Returns 0 on success, < 0 otherwise. */ @@ -2119,22 +2125,15 @@ static void complete_scsi_command(struct CommandList *cp) if (unlikely(ei->CommandStatus == CMD_CTLR_LOCKUP)) { /* DID_NO_CONNECT will prevent a retry */ cmd->result = DID_NO_CONNECT << 16; - cmd_free(h, cp); - cmd->scsi_done(cmd); - return; + return hpsa_cmd_free_and_done(h, cp, cmd); } if (cp->cmd_type == CMD_IOACCEL2) return process_ioaccel2_completion(h, cp, cmd, dev); scsi_set_resid(cmd, ei->ResidualCnt); - if (ei->CommandStatus == 0) { - if (cp->cmd_type == CMD_IOACCEL1) - atomic_dec(&cp->phys_disk->ioaccel_cmds_out); - cmd_free(h, cp); - cmd->scsi_done(cmd); - return; - } + if (ei->CommandStatus == 0) + return hpsa_cmd_free_and_done(h, cp, cmd); /* For I/O accelerator commands, copy over some fields to the normal * CISS header used below for error handling. @@ -2156,10 +2155,7 @@ static void complete_scsi_command(struct CommandList *cp) if (is_logical_dev_addr_mode(dev->scsi3addr)) { if (ei->CommandStatus == CMD_IOACCEL_DISABLED) dev->offload_enabled = 0; - INIT_WORK(&cp->work, hpsa_command_resubmit_worker); - queue_work_on(raw_smp_processor_id(), - h->resubmit_wq, &cp->work); - return; + return hpsa_retry_cmd(h, cp); } } @@ -2290,8 +2286,8 @@ static void complete_scsi_command(struct CommandList *cp) dev_warn(&h->pdev->dev, "cp %p returned unknown status %x\n", cp, ei->CommandStatus); } - cmd_free(h, cp); - cmd->scsi_done(cmd); + + return hpsa_cmd_free_and_done(h, cp, cmd); } static void hpsa_pci_unmap(struct pci_dev *pdev, @@ -4544,16 +4540,13 @@ static void hpsa_command_resubmit_worker(struct work_struct *work) { struct scsi_cmnd *cmd; struct hpsa_scsi_dev_t *dev; - struct CommandList *c = - container_of(work, struct CommandList, work); + struct CommandList *c = container_of(work, struct CommandList, work);
[PATCH v3 29/42] hpsa: refactor and rework support for sending TEST_UNIT_READY
From: Webb Scales Factor out the code which sends the TEST_UNIT_READY from wait_for_device_to_become_ready() into its own function. Move the code which waits for the TEST_UNIT_READY from wait_for_device_to_become_ready() into its own function. If a logical drive has failed, resetting it will ensure outstanding commands are completed, but polling it with TURs after the reset will not work because the TURs will never report good status. So successful TUR should not be a condition of success for the device reset error handler. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Webb Scales Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 117 ++- 1 file changed, 87 insertions(+), 30 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 1cae336..3751df3 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -4822,51 +4822,108 @@ static int hpsa_register_scsi(struct ctlr_info *h) return -ENOMEM; } -static int wait_for_device_to_become_ready(struct ctlr_info *h, - unsigned char lunaddr[]) +/* + * Send a TEST_UNIT_READY command to the specified LUN using the specified + * reply queue; returns zero if the unit is ready, and non-zero otherwise. + */ +static int hpsa_send_test_unit_ready(struct ctlr_info *h, + struct CommandList *c, unsigned char lunaddr[], + int reply_queue) +{ + int rc; + + /* Send the Test Unit Ready, fill_cmd can't fail, no mapping */ + (void) fill_cmd(c, TEST_UNIT_READY, h, + NULL, 0, 0, lunaddr, TYPE_CMD); + rc = hpsa_scsi_do_simple_cmd(h, c, reply_queue, NO_TIMEOUT); + if (rc) + return rc; + /* no unmap needed here because no data xfer. */ + + /* Check if the unit is already ready. */ + if (c->err_info->CommandStatus == CMD_SUCCESS) + return 0; + + /* +* The first command sent after reset will receive "unit attention" to +* indicate that the LUN has been reset...this is actually what we're +* looking for (but, success is good too). +*/ + if (c->err_info->CommandStatus == CMD_TARGET_STATUS && + c->err_info->ScsiStatus == SAM_STAT_CHECK_CONDITION && + (c->err_info->SenseInfo[2] == NO_SENSE || +c->err_info->SenseInfo[2] == UNIT_ATTENTION)) + return 0; + + return 1; +} + +/* + * Wait for a TEST_UNIT_READY command to complete, retrying as necessary; + * returns zero when the unit is ready, and non-zero when giving up. + */ +static int hpsa_wait_for_test_unit_ready(struct ctlr_info *h, + struct CommandList *c, + unsigned char lunaddr[], int reply_queue) { int rc; int count = 0; int waittime = 1; /* seconds */ - struct CommandList *c; - - c = cmd_alloc(h); /* Send test unit ready until device ready, or give up. */ - while (count < HPSA_TUR_RETRY_LIMIT) { + for (count = 0; count < HPSA_TUR_RETRY_LIMIT; count++) { - /* Wait for a bit. do this first, because if we send + /* +* Wait for a bit. do this first, because if we send * the TUR right away, the reset will just abort it. */ msleep(1000 * waittime); - count++; - rc = 0; /* Device ready. */ + + rc = hpsa_send_test_unit_ready(h, c, lunaddr, reply_queue); + if (!rc) + break; /* Increase wait time with each try, up to a point. */ if (waittime < HPSA_MAX_WAIT_INTERVAL_SECS) - waittime = waittime * 2; + waittime *= 2; - /* Send the Test Unit Ready, fill_cmd can't fail, no mapping */ - (void) fill_cmd(c, TEST_UNIT_READY, h, - NULL, 0, 0, lunaddr, TYPE_CMD); - rc = hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE, - NO_TIMEOUT); - if (rc) - goto do_it_again; - /* no unmap needed here because no data xfer. */ + dev_warn(&h->pdev->dev, +"waiting %d secs for device to become ready.\n", +waittime); + } - if (c->err_info->CommandStatus == CMD_SUCCESS) - break; + return rc; +} - if (c->err_info->CommandStatus == CMD_TARGET_STATUS && - c->err_info->ScsiStatus == SAM_STAT_CHECK_CONDITION && - (c->err_info->SenseInfo[2] == NO_SENSE || - c->err_info->SenseInfo[2] == UNIT_ATTENTION)) +static int wait_for_device_to_become_ready(struct ctlr_info *h,
[PATCH v3 26/42] hpsa: add support sending aborts to physical devices via the ioaccel2 path
From: Stephen Cameron add support for tmf when in ioaccel2 mode Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Joe Handzik Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 136 +-- drivers/scsi/hpsa.h |1 drivers/scsi/hpsa_cmd.h |6 +- 3 files changed, 135 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 7d0e226..e9642dd 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -861,6 +861,28 @@ static void set_ioaccel1_performant_mode(struct ctlr_info *h, IOACCEL1_BUSADDR_CMDTYPE; } +static void set_ioaccel2_tmf_performant_mode(struct ctlr_info *h, + struct CommandList *c, + int reply_queue) +{ + struct hpsa_tmf_struct *cp = (struct hpsa_tmf_struct *) + &h->ioaccel2_cmd_pool[c->cmdindex]; + + /* Tell the controller to post the reply to the queue for this +* processor. This seems to give the best I/O throughput. +*/ + if (likely(reply_queue == DEFAULT_REPLY_QUEUE)) + cp->reply_queue = smp_processor_id() % h->nreply_queues; + else + cp->reply_queue = reply_queue % h->nreply_queues; + /* Set the bits in the address sent down to include: +* - performant mode bit not used in ioaccel mode 2 +* - pull count (bits 0-3) +* - command type isn't needed for ioaccel2 +*/ + c->busaddr |= h->ioaccel2_blockFetchTable[0]; +} + static void set_ioaccel2_performant_mode(struct ctlr_info *h, struct CommandList *c, int reply_queue) @@ -927,6 +949,10 @@ static void __enqueue_cmd_and_start_io(struct ctlr_info *h, set_ioaccel2_performant_mode(h, c, reply_queue); writel(c->busaddr, h->vaddr + IOACCEL2_INBOUND_POSTQ_32); break; + case IOACCEL2_TMF: + set_ioaccel2_tmf_performant_mode(h, c, reply_queue); + writel(c->busaddr, h->vaddr + IOACCEL2_INBOUND_POSTQ_32); + break; default: set_performant_mode(h, c, reply_queue); h->access.submit_command(h, c); @@ -4954,6 +4980,47 @@ static int hpsa_send_abort(struct ctlr_info *h, unsigned char *scsi3addr, return rc; } +static void setup_ioaccel2_abort_cmd(struct CommandList *c, struct ctlr_info *h, + struct CommandList *command_to_abort, int reply_queue) +{ + struct io_accel2_cmd *c2 = &h->ioaccel2_cmd_pool[c->cmdindex]; + struct hpsa_tmf_struct *ac = (struct hpsa_tmf_struct *) c2; + struct io_accel2_cmd *c2a = + &h->ioaccel2_cmd_pool[command_to_abort->cmdindex]; + struct scsi_cmnd *scmd = + (struct scsi_cmnd *) command_to_abort->scsi_cmd; + struct hpsa_scsi_dev_t *dev = scmd->device->hostdata; + + /* +* We're overlaying struct hpsa_tmf_struct on top of something which +* was allocated as a struct io_accel2_cmd, so we better be sure it +* actually fits, and doesn't overrun the error info space. +*/ + BUILD_BUG_ON(sizeof(struct hpsa_tmf_struct) > + sizeof(struct io_accel2_cmd)); + BUG_ON(offsetof(struct io_accel2_cmd, error_data) < + offsetof(struct hpsa_tmf_struct, error_len) + + sizeof(ac->error_len)); + + c->cmd_type = IOACCEL2_TMF; + /* Adjust the DMA address to point to the accelerated command buffer */ + c->busaddr = (u32) h->ioaccel2_cmd_pool_dhandle + + (c->cmdindex * sizeof(struct io_accel2_cmd)); + BUG_ON(c->busaddr & 0x007F); + + memset(ac, 0, sizeof(*c2)); /* yes this is correct */ + ac->iu_type = IOACCEL2_IU_TMF_TYPE; + ac->reply_queue = reply_queue; + ac->tmf = IOACCEL2_TMF_ABORT; + ac->it_nexus = cpu_to_le32(dev->ioaccel_handle); + memset(ac->lun_id, 0, sizeof(ac->lun_id)); + ac->tag = cpu_to_le64(c->cmdindex << DIRECT_LOOKUP_SHIFT); + ac->abort_tag = cpu_to_le64(le32_to_cpu(c2a->Tag)); + ac->error_ptr = cpu_to_le64(c->busaddr + + offsetof(struct io_accel2_cmd, error_data)); + ac->error_len = cpu_to_le32(sizeof(c2->error_data)); +} + /* ioaccel2 path firmware cannot handle abort task requests. * Change abort requests to physical target reset, and send to the * address of the physical disk used for the ioaccel 2 command. @@ -5032,17 +5099,72 @@ static int hpsa_send_reset_as_abort_ioaccel2(struct ctlr_info *h, return rc; /* success */ } +static int hpsa_send_abort_ioaccel2(struct ctlr_info *h, + struct CommandList *abort, int reply_queue) +{ + int rc = IO_OK; + struct CommandList *c; +
[PATCH v3 34/42] hpsa: fix try_soft_reset error handling
From: Robert Elliott If registering the special interrupt handlers in hpsa_init_one before a soft reset fails, the error exit needs to deallocate everything that was allocated before. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Robert Elliott Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 16 +++- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 0afc48b..fdf36a7 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -7810,9 +7810,15 @@ reinit_after_soft_reset: dev_warn(&h->pdev->dev, "Failed to request_irq after soft reset.\n"); /* -* clean4 starts with free_irqs, but that was just -* done. Then, request_irqs_failed, so there is -* nothing to free. So, goto the next label. +* cannot goto clean7 or free_irqs will be called +* again. Instead, do its work +*/ + hpsa_free_performant_mode(h); /* clean7 */ + hpsa_free_sg_chain_blocks(h); /* clean6 */ + hpsa_free_cmd_pool(h); /* clean5 */ + /* +* skip hpsa_free_irqs(h) clean4 since that +* was just called before request_irqs failed */ goto clean3; } @@ -7820,7 +7826,7 @@ reinit_after_soft_reset: rc = hpsa_kdump_soft_reset(h); if (rc) /* Neither hard nor soft reset worked, we're hosed. */ - goto clean4; + goto clean7; dev_info(&h->pdev->dev, "Board READY.\n"); dev_info(&h->pdev->dev, @@ -7841,7 +7847,7 @@ reinit_after_soft_reset: hpsa_undo_allocations_after_kdump_soft_reset(h); try_soft_reset = 0; if (rc) - /* don't go to clean4, we already unallocated */ + /* don't goto clean, we already unallocated */ return -ENODEV; goto reinit_after_soft_reset; -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 28/42] hpsa: don't return abort request until target is complete
From: Webb Scales Don't return from the abort request until the target command is complete. Mark outstanding commands which have a pending abort, and do not send them to the host if we can avoid it. If the current command has been aborted, do not call the SCSI command completion routine from the I/O path: when the abort returns successfully, the SCSI mid-layer will handle the completion implicitly. The following race was possible in theory. 1. LLD is requested to abort a scsi command 2. scsi command completes 3. The struct CommandList associated with 2 is made available. 4. new io request to LLD to another LUN re-uses struct CommandList 5. abort handler follows scsi_cmnd->host_scribble and finds struct CommandList and tries to aborts it. Now we have aborted the wrong command. Fix by resetting the scsi_cmd field of struct CommandList upon completion and making the abort handler check that the scsi_cmd pointer in the CommadList struct matches the scsi_cmnd that it has been asked to abort. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Webb Scales Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 120 +++ drivers/scsi/hpsa.h |1 drivers/scsi/hpsa_cmd.h |2 + 3 files changed, 93 insertions(+), 30 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index b0949f7..1cae336 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -195,6 +195,10 @@ static struct board_type products[] = { {0x103C, "Unknown Smart Array", &SA5_access}, }; +#define SCSI_CMD_BUSY ((struct scsi_cmnd *)&hpsa_cmd_busy) +static const struct scsi_cmnd hpsa_cmd_busy; +#define SCSI_CMD_IDLE ((struct scsi_cmnd *)&hpsa_cmd_idle) +static const struct scsi_cmnd hpsa_cmd_idle; static int number_of_controllers; static irqreturn_t do_hpsa_intr_intx(int irq, void *dev_id); @@ -270,6 +274,11 @@ static inline struct ctlr_info *shost_to_hba(struct Scsi_Host *sh) return (struct ctlr_info *) *priv; } +static inline bool hpsa_is_cmd_idle(struct CommandList *c) +{ + return c->scsi_cmd == SCSI_CMD_IDLE; +} + /* extract sense key, asc, and ascq from sense data. -1 means invalid. */ static void decode_sense_data(const u8 *sense_data, int sense_data_len, int *sense_key, int *asc, int *ascq) @@ -959,9 +968,11 @@ static void __enqueue_cmd_and_start_io(struct ctlr_info *h, } } -static void enqueue_cmd_and_start_io(struct ctlr_info *h, - struct CommandList *c) +static void enqueue_cmd_and_start_io(struct ctlr_info *h, struct CommandList *c) { + if (unlikely(c->abort_pending)) + return finish_cmd(c); + __enqueue_cmd_and_start_io(h, c, DEFAULT_REPLY_QUEUE); } @@ -2010,9 +2021,36 @@ static int handle_ioaccel_mode2_error(struct ctlr_info *h, return retry; /* retry on raid path? */ } +static void hpsa_cmd_resolve_events(struct ctlr_info *h, + struct CommandList *c) +{ + /* +* Prevent the following race in the abort handler: +* +* 1. LLD is requested to abort a SCSI command +* 2. The SCSI command completes +* 3. The struct CommandList associated with step 2 is made available +* 4. New I/O request to LLD to another LUN re-uses struct CommandList +* 5. Abort handler follows scsi_cmnd->host_scribble and +*finds struct CommandList and tries to aborts it +* Now we have aborted the wrong command. +* +* Clear c->scsi_cmd here so that the abort handler will know this +* command has completed. Then, check to see if the abort handler is +* waiting for this command, and, if so, wake it. +*/ + c->scsi_cmd = SCSI_CMD_IDLE; + mb(); /* Ensure c->scsi_cmd is set to SCSI_CMD_IDLE */ + if (c->abort_pending) { + c->abort_pending = false; + wake_up_all(&h->abort_sync_wait_queue); + } +} + static void hpsa_cmd_free_and_done(struct ctlr_info *h, struct CommandList *c, struct scsi_cmnd *cmd) { + hpsa_cmd_resolve_events(h, c); cmd_free(h, c); cmd->scsi_done(cmd); } @@ -2023,6 +2061,21 @@ static void hpsa_retry_cmd(struct ctlr_info *h, struct CommandList *c) queue_work_on(raw_smp_processor_id(), h->resubmit_wq, &c->work); } +static void hpsa_set_scsi_cmd_aborted(struct scsi_cmnd *cmd) +{ + cmd->result = DID_ABORT << 16; +} + +static void hpsa_cmd_abort_and_free(struct ctlr_info *h, struct CommandList *c, + struct scsi_cmnd *cmd) +{ + hpsa_set_scsi_cmd_aborted(cmd); + dev_warn(&h->pdev->dev, "CDB %16phN was aborted with status 0x%x\n", +c->Request.CDB, c->err_info->ScsiStatus); + hpsa_cmd_resolve_events(h, c); + cmd_free(h, c); /* FIX-ME: change to cmd_tagged_free(h, c) */ +} + static void
[PATCH v3 33/42] hpsa: cleanup for init_one step 2 in kdump
From: Robert Elliott In hpsa_undo_allocations_after_kdump_soft_reset, the things allocated in hpsa_init_one step 2 - h->resubmit_wq and h->lockup_detected need to be freed, in the right order. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Robert Elliott Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 10 ++ 1 file changed, 10 insertions(+) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index f26e6bc..0afc48b 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -7422,6 +7422,16 @@ static void hpsa_undo_allocations_after_kdump_soft_reset(struct ctlr_info *h) hpsa_free_cmd_pool(h); /* init_one 5 */ hpsa_free_irqs(h); /* init_one 4 */ hpsa_free_pci_init(h); /* init_one 3 */ + free_percpu(h->lockup_detected);/* init_one 2 */ + h->lockup_detected = NULL; /* init_one 2 */ + if (h->resubmit_wq) { + destroy_workqueue(h->resubmit_wq); /* init_one 1 */ + h->resubmit_wq = NULL; + } + if (h->rescan_ctlr_wq) { + destroy_workqueue(h->rescan_ctlr_wq); + h->rescan_ctlr_wq = NULL; + } kfree(h); /* init_one 1 */ } -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 35/42] hpsa: create workqueue after the driver is ready for use
From: Robert Elliott Don't create the resubmit workqueue in hpsa_init_one until everything else is ready to use, so everything can be freed in reverse order of when they were allocated without risking freeing things while workqueue items are still active. Destroy the workqueue in the right order in hpsa_undo_allocations_after_kdump_soft_reset too. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Robert Elliott Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 60 ++- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index fdf36a7..0057236 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -7714,30 +7714,18 @@ reinit_after_soft_reset: atomic_set(&h->passthru_cmds_avail, HPSA_MAX_CONCURRENT_PASSTHRUS); atomic_set(&h->abort_cmds_available, HPSA_CMDS_RESERVED_FOR_ABORTS); - h->rescan_ctlr_wq = hpsa_create_controller_wq(h, "rescan"); - if (!h->rescan_ctlr_wq) { - rc = -ENOMEM; - goto clean1; - } - - h->resubmit_wq = hpsa_create_controller_wq(h, "resubmit"); - if (!h->resubmit_wq) { - rc = -ENOMEM; - goto clean1;/* aer/h */ - } - /* Allocate and clear per-cpu variable lockup_detected */ h->lockup_detected = alloc_percpu(u32); if (!h->lockup_detected) { dev_err(&h->pdev->dev, "Failed to allocate lockup detector\n"); rc = -ENOMEM; - goto clean1;/* wq/aer/h */ + goto clean1;/* aer/h */ } set_lockup_detected_for_all_cpus(h, 0); rc = hpsa_pci_init(h); if (rc) - goto clean2;/* lockup, wq/aer/h */ + goto clean2;/* lockup, aer/h */ sprintf(h->devname, HPSA "%d", number_of_controllers); h->ctlr = number_of_controllers; @@ -7753,7 +7741,7 @@ reinit_after_soft_reset: dac = 0; } else { dev_err(&pdev->dev, "no suitable DMA available\n"); - goto clean3;/* pci, lockup, wq/aer/h */ + goto clean3;/* pci, lockup, aer/h */ } } @@ -7762,16 +7750,16 @@ reinit_after_soft_reset: rc = hpsa_request_irqs(h, do_hpsa_intr_msi, do_hpsa_intr_intx); if (rc) - goto clean3;/* pci, lockup, wq/aer/h */ + goto clean3;/* pci, lockup, aer/h */ 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"); rc = hpsa_alloc_cmd_pool(h); if (rc) - goto clean4;/* irq, pci, lockup, wq/aer/h */ + goto clean4;/* irq, pci, lockup, aer/h */ rc = hpsa_alloc_sg_chain_blocks(h); if (rc) - goto clean5;/* cmd, irq, pci, lockup, wq/aer/h */ + goto clean5;/* cmd, irq, pci, lockup, aer/h */ init_waitqueue_head(&h->scan_wait_queue); init_waitqueue_head(&h->abort_cmd_wait_queue); init_waitqueue_head(&h->abort_sync_wait_queue); @@ -7784,7 +7772,20 @@ reinit_after_soft_reset: spin_lock_init(&h->devlock); rc = hpsa_put_ctlr_into_performant_mode(h); if (rc) - goto clean6;/* sg, cmd, irq, pci, lockup, wq/aer/h */ + goto clean6;/* sg, cmd, irq, pci, lockup, aer/h */ + + /* create the resubmit workqueue */ + h->rescan_ctlr_wq = hpsa_create_controller_wq(h, "rescan"); + if (!h->rescan_ctlr_wq) { + rc = -ENOMEM; + goto clean7; + } + + h->resubmit_wq = hpsa_create_controller_wq(h, "resubmit"); + if (!h->resubmit_wq) { + rc = -ENOMEM; + goto clean7;/* aer/h */ + } /* * At this point, the controller is ready to take commands. @@ -7826,7 +7827,7 @@ reinit_after_soft_reset: rc = hpsa_kdump_soft_reset(h); if (rc) /* Neither hard nor soft reset worked, we're hosed. */ - goto clean7; + goto clean8; dev_info(&h->pdev->dev, "Board READY.\n"); dev_info(&h->pdev->dev, @@ -7863,7 +7864,7 @@ reinit_after_soft_reset: hpsa_hba_inquiry(h); rc = hpsa_register_scsi(h); /* hook ourselves into SCSI subsystem */ if (rc) - goto clean7; + goto clean8; /* wq, perf, sg, cmd, irq, pci, lockup, aer/h */ /* Monitor the controller for firmware lockups */ h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL; @@ -7875,19 +7876,20 @@ reinit_after_soft_reset: h->heartbeat_sample_interval); return 0; -clean7: /* perf, sg, cmd, irq, pci,
[PATCH v3 36/42] hpsa: add interrupt number to /proc/interrupts interrupt name
From: Robert Elliott Add the interrupt number to the interrupt names that appear in /proc/interrupts, so they are unique Also, delete the IRQ and DAC prints. Other parts of the kernel already print the IRQ assignments, and dual-address-cycle support has not been interesting since the parallel PCI bus went from 32 to 64 bits wide. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Robert Elliott Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 20 ++-- drivers/scsi/hpsa.h |1 + 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 0057236..34c178c 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -7337,8 +7337,9 @@ static int hpsa_request_irqs(struct ctlr_info *h, if (h->intr_mode == PERF_MODE_INT && h->msix_vector > 0) { /* If performant mode and MSI-X, use multiple reply queues */ for (i = 0; i < h->msix_vector; i++) { + sprintf(h->intrname[i], "%s-msix%d", h->devname, i); rc = request_irq(h->intr[i], msixhandler, - 0, h->devname, + 0, h->intrname[i], &h->q[i]); if (rc) { int j; @@ -7359,12 +7360,22 @@ static int hpsa_request_irqs(struct ctlr_info *h, } else { /* Use single reply pool */ if (h->msix_vector > 0 || h->msi_vector) { + if (h->msix_vector) + sprintf(h->intrname[h->intr_mode], + "%s-msix", h->devname); + else + sprintf(h->intrname[h->intr_mode], + "%s-msi", h->devname); rc = request_irq(h->intr[h->intr_mode], - msixhandler, 0, h->devname, + msixhandler, 0, + h->intrname[h->intr_mode], &h->q[h->intr_mode]); } else { + sprintf(h->intrname[h->intr_mode], + "%s-intx", h->devname); rc = request_irq(h->intr[h->intr_mode], - intxhandler, IRQF_SHARED, h->devname, + intxhandler, IRQF_SHARED, + h->intrname[h->intr_mode], &h->q[h->intr_mode]); } irq_set_affinity_hint(h->intr[h->intr_mode], NULL); @@ -7751,9 +7762,6 @@ reinit_after_soft_reset: rc = hpsa_request_irqs(h, do_hpsa_intr_msi, do_hpsa_intr_intx); if (rc) goto clean3;/* pci, lockup, aer/h */ - 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"); rc = hpsa_alloc_cmd_pool(h); if (rc) goto clean4;/* irq, pci, lockup, aer/h */ diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index 7cb8586..3ec8934 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -220,6 +220,7 @@ struct ctlr_info { int remove_in_progress; /* Address of h->q[x] is passed to intr handler to know which queue */ u8 q[MAX_REPLY_QUEUES]; + char intrname[MAX_REPLY_QUEUES][16];/* "hpsa0-msix00" names */ u32 TMFSupportFlags; /* cache what task mgmt funcs are supported. */ #define HPSATMF_BITS_SUPPORTED (1 << 0) #define HPSATMF_PHYS_LUN_RESET (1 << 1) -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 39/42] hpsa: propagate the error code in hpsa_kdump_soft_reset
From: Robert Elliott If hpsa_wait_for_board_state fails, hpsa_kdump_soft_reset should propagate its return value (e.g., -ENODEV) rather than just returning -1. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Robert Elliott Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 11 +++ 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 511b7ab..3987400 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -7480,19 +7480,22 @@ static int hpsa_request_irqs(struct ctlr_info *h, static int hpsa_kdump_soft_reset(struct ctlr_info *h) { + int rc; hpsa_send_host_reset(h, RAID_CTLR_LUNID, HPSA_RESET_TYPE_CONTROLLER); 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)) { + rc = hpsa_wait_for_board_state(h->pdev, h->vaddr, BOARD_NOT_READY); + if (rc) { dev_warn(&h->pdev->dev, "Soft reset had no effect.\n"); - return -1; + return rc; } dev_info(&h->pdev->dev, "Board reset, awaiting READY status.\n"); - if (hpsa_wait_for_board_state(h->pdev, h->vaddr, BOARD_READY)) { + rc = hpsa_wait_for_board_state(h->pdev, h->vaddr, BOARD_READY); + if (rc) { dev_warn(&h->pdev->dev, "Board failed to become ready " "after soft reset.\n"); - return -1; + return rc; } return 0; -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 40/42] hpsa: cleanup reset
From: Webb Scales Synchronize completion the reset with completion of outstanding commands Extending the newly-added synchronous abort functionality, now also synchronize resets with the completion of outstanding commands. Rename the wait queue to reflect the fact that it's being used for both types of waits. Also, don't complete commands which are terminated due to a reset operation. fix for controller lockup during reset Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Webb Scales Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 200 +-- drivers/scsi/hpsa.h |5 + drivers/scsi/hpsa_cmd.h |1 3 files changed, 178 insertions(+), 28 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 3987400..96e1d02 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -283,6 +283,11 @@ static inline bool hpsa_is_cmd_idle(struct CommandList *c) return c->scsi_cmd == SCSI_CMD_IDLE; } +static inline bool hpsa_is_pending_event(struct CommandList *c) +{ + return c->abort_pending || c->reset_pending; +} + /* extract sense key, asc, and ascq from sense data. -1 means invalid. */ static void decode_sense_data(const u8 *sense_data, int sense_data_len, int *sense_key, int *asc, int *ascq) @@ -977,7 +982,7 @@ static void __enqueue_cmd_and_start_io(struct ctlr_info *h, static void enqueue_cmd_and_start_io(struct ctlr_info *h, struct CommandList *c) { - if (unlikely(c->abort_pending)) + if (unlikely(hpsa_is_pending_event(c))) return finish_cmd(c); __enqueue_cmd_and_start_io(h, c, DEFAULT_REPLY_QUEUE); @@ -1479,6 +1484,8 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h, if (nraid_map_entries > RAID_MAP_MAX_ENTRIES) nraid_map_entries = RAID_MAP_MAX_ENTRIES; + logical_drive->nphysical_disks = nraid_map_entries; + qdepth = 0; for (i = 0; i < nraid_map_entries; i++) { logical_drive->phys_disk[i] = NULL; @@ -2031,6 +2038,8 @@ static int handle_ioaccel_mode2_error(struct ctlr_info *h, static void hpsa_cmd_resolve_events(struct ctlr_info *h, struct CommandList *c) { + bool do_wake = false; + /* * Prevent the following race in the abort handler: * @@ -2042,16 +2051,35 @@ static void hpsa_cmd_resolve_events(struct ctlr_info *h, *finds struct CommandList and tries to aborts it * Now we have aborted the wrong command. * -* Clear c->scsi_cmd here so that the abort handler will know this -* command has completed. Then, check to see if the abort handler is +* Reset c->scsi_cmd here so that the abort or reset handler will know +* this command has completed. Then, check to see if the handler is * waiting for this command, and, if so, wake it. */ c->scsi_cmd = SCSI_CMD_IDLE; - mb(); /* Ensure c->scsi_cmd is set to SCSI_CMD_IDLE */ + mb(); /* Declare command idle before checking for pending events. */ if (c->abort_pending) { + do_wake = true; c->abort_pending = false; - wake_up_all(&h->abort_sync_wait_queue); } + if (c->reset_pending) { + unsigned long flags; + struct hpsa_scsi_dev_t *dev; + + /* +* There appears to be a reset pending; lock the lock and +* reconfirm. If so, then decrement the count of outstanding +* commands and wake the reset command if this is the last one. +*/ + spin_lock_irqsave(&h->lock, flags); + dev = c->reset_pending; /* Re-fetch under the lock. */ + if (dev && atomic_dec_and_test(&dev->reset_cmds_out)) + do_wake = true; + c->reset_pending = NULL; + spin_unlock_irqrestore(&h->lock, flags); + } + + if (do_wake) + wake_up_all(&h->event_sync_wait_queue); } static void hpsa_cmd_resolve_and_free(struct ctlr_info *h, @@ -2099,10 +2127,6 @@ static void process_ioaccel2_completion(struct ctlr_info *h, c2->error_data.status == 0)) return hpsa_cmd_free_and_done(h, c, cmd); - /* don't requeue a command which is being aborted */ - if (unlikely(c->abort_pending)) - return hpsa_cmd_abort_and_free(h, c, cmd); - /* * Any RAID offload error results in retry which will use * the normal I/O path so the controller can handle whatever's @@ -2197,6 +2221,13 @@ static void complete_scsi_command(struct CommandList *cp) return hpsa_cmd_free_and_done(h, cp, cmd); } + if ((unlikely(hpsa_is_pending_event(cp { + if (cp->reset_pending) + return hpsa_cmd_resolve_an
[PATCH v3 37/42] hpsa: use block layer tag for command allocation
From: Webb Scales Rework slave allocation: - separate the tagging support setup from the hostdata setup - make the hostdata setup act consistently when the lookup fails - make the hostdata setup act consistently when the device is not added - set up the queue depth consistently across these scenarios - if the block layer mq support is not available, explicitly enable and activate the SCSI layer tcq support (and do this at allocation-time so that the tags will be available for INQUIRY commands) Tweak slave configuration so that devices which are masked are also not attached. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Webb Scales Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 153 +-- drivers/scsi/hpsa.h |1 2 files changed, 123 insertions(+), 31 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 34c178c..4e34a62 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -212,6 +213,9 @@ static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd, static void cmd_free(struct ctlr_info *h, struct CommandList *c); static struct CommandList *cmd_alloc(struct ctlr_info *h); +static void cmd_tagged_free(struct ctlr_info *h, struct CommandList *c); +static struct CommandList *cmd_tagged_alloc(struct ctlr_info *h, + struct scsi_cmnd *scmd); static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, void *buff, size_t size, u16 page_code, unsigned char *scsi3addr, int cmd_type); @@ -2047,11 +2051,17 @@ static void hpsa_cmd_resolve_events(struct ctlr_info *h, } } +static void hpsa_cmd_resolve_and_free(struct ctlr_info *h, + struct CommandList *c) +{ + hpsa_cmd_resolve_events(h, c); + cmd_tagged_free(h, c); +} + static void hpsa_cmd_free_and_done(struct ctlr_info *h, struct CommandList *c, struct scsi_cmnd *cmd) { - hpsa_cmd_resolve_events(h, c); - cmd_free(h, c); + hpsa_cmd_resolve_and_free(h, c); cmd->scsi_done(cmd); } @@ -2072,8 +2082,7 @@ static void hpsa_cmd_abort_and_free(struct ctlr_info *h, struct CommandList *c, hpsa_set_scsi_cmd_aborted(cmd); dev_warn(&h->pdev->dev, "CDB %16phN was aborted with status 0x%x\n", c->Request.CDB, c->err_info->ScsiStatus); - hpsa_cmd_resolve_events(h, c); - cmd_free(h, c); /* FIX-ME: change to cmd_tagged_free(h, c) */ + hpsa_cmd_resolve_and_free(h, c); } static void process_ioaccel2_completion(struct ctlr_info *h, @@ -4535,7 +4544,7 @@ static int hpsa_ciss_submit(struct ctlr_info *h, } if (hpsa_scatter_gather(h, c, cmd) < 0) { /* Fill SG list */ - cmd_free(h, c); + hpsa_cmd_resolve_and_free(h, c); return SCSI_MLQUEUE_HOST_BUSY; } enqueue_cmd_and_start_io(h, c); @@ -4581,6 +4590,8 @@ static inline void hpsa_cmd_partial_init(struct ctlr_info *h, int index, { dma_addr_t cmd_dma_handle = h->cmd_pool_dhandle + index * sizeof(*c); + BUG_ON(c->cmdindex != index); + memset(c->Request.CDB, 0, sizeof(c->Request.CDB)); memset(c->err_info, 0, sizeof(*c->err_info)); c->busaddr = (u32) cmd_dma_handle; @@ -4675,27 +4686,24 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd) /* Get the ptr to our adapter structure out of cmd->host. */ h = sdev_to_hba(cmd->device); + + BUG_ON(cmd->request->tag < 0); + dev = cmd->device->hostdata; if (!dev) { cmd->result = DID_NO_CONNECT << 16; cmd->scsi_done(cmd); return 0; } - memcpy(scsi3addr, dev->scsi3addr, sizeof(scsi3addr)); - if (unlikely(lockup_detected(h))) { - cmd->result = DID_NO_CONNECT << 16; - cmd->scsi_done(cmd); - return 0; - } - c = cmd_alloc(h); + memcpy(scsi3addr, dev->scsi3addr, sizeof(scsi3addr)); if (unlikely(lockup_detected(h))) { cmd->result = DID_NO_CONNECT << 16; - cmd_free(h, c); cmd->scsi_done(cmd); return 0; } + c = cmd_tagged_alloc(h, cmd); /* * Call alternate submit routine for I/O accelerated commands. @@ -4708,7 +4716,7 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd) if (rc == 0) return 0; if (rc == SCSI_MLQUEUE_HOST_BUSY) { - cmd_free(h, c); + hpsa_cmd_resolve_and_free(h, c); return SCSI_MLQUEUE_HOST_BUSY; } } @@ -4822,15 +4830,23 @@ static int hpsa_re
[PATCH v3 41/42] hpsa: change driver version
update driver version Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/hpsa.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 96e1d02..893bb50 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -58,7 +58,7 @@ #include "hpsa.h" /* HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.' */ -#define HPSA_DRIVER_VERSION "3.4.4-1" +#define HPSA_DRIVER_VERSION "3.4.10-0" #define DRIVER_NAME "HP HPSA Driver (v " HPSA_DRIVER_VERSION ")" #define HPSA "hpsa" -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 42/42] hpsa: add PMC to copyright
need to add PMC to copyright notice and update the Hewlett-Packard copyright notification. Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Reviewed-by: Justin Lindley Signed-off-by: Don Brace --- drivers/scsi/hpsa.c |3 ++- drivers/scsi/hpsa.h |3 ++- drivers/scsi/hpsa_cmd.h |3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 893bb50..33ad6eb 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1,6 +1,7 @@ /* *Disk Array driver for HP Smart Array SAS controllers - *Copyright 2000, 2014 Hewlett-Packard Development Company, L.P. + *Copyright 2014-2015 PMC-Sierra, Inc. + *Portions Copyright 2008-2014 Hewlett-Packard Development Company, L.P. * *This program is free software; you can redistribute it and/or modify *it under the terms of the GNU General Public License as published by diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index 6ee4da6..80cfc79 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -1,6 +1,7 @@ /* *Disk Array driver for HP Smart Array SAS controllers - *Copyright 2000, 2014 Hewlett-Packard Development Company, L.P. + *Copyright 2014-2015 PMC-Sierra, Inc. + *Portions Copyright 2008-2014 Hewlett-Packard Development Company, L.P. * *This program is free software; you can redistribute it and/or modify *it under the terms of the GNU General Public License as published by diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h index c601622..23a8f0d 100644 --- a/drivers/scsi/hpsa_cmd.h +++ b/drivers/scsi/hpsa_cmd.h @@ -1,6 +1,7 @@ /* *Disk Array driver for HP Smart Array SAS controllers - *Copyright 2000, 2014 Hewlett-Packard Development Company, L.P. + *Copyright 2014-2015 PMC-Sierra, Inc. + *Portions Copyright 2008-2014 Hewlett-Packard Development Company, L.P. * *This program is free software; you can redistribute it and/or modify *it under the terms of the GNU General Public License as published by -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 38/42] hpsa: use scsi host_no as hpsa controller number
From: Robert Elliott Rather than numbering the hpsa controllers with an incrementing 0..n value (e.g., that shows up in /proc/interrupts), use the scsi midlayer host_no (e.g. matching /sys/class/scsi_host/hostNN). Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Robert Elliott Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 134 --- 1 file changed, 74 insertions(+), 60 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 4e34a62..511b7ab 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -324,32 +324,35 @@ static int check_for_unit_attention(struct ctlr_info *h, switch (asc) { case STATE_CHANGED: dev_warn(&h->pdev->dev, - HPSA "%d: a state change detected, command retried\n", - h->ctlr); + "%s: a state change detected, command retried\n", + h->devname); break; case LUN_FAILED: dev_warn(&h->pdev->dev, - HPSA "%d: LUN failure detected\n", h->ctlr); + "%s: LUN failure detected\n", h->devname); break; case REPORT_LUNS_CHANGED: dev_warn(&h->pdev->dev, - HPSA "%d: report LUN data changed\n", h->ctlr); + "%s: report LUN data changed\n", h->devname); /* * Note: this REPORT_LUNS_CHANGED condition only occurs on the external * target (array) devices. */ break; case POWER_OR_RESET: - dev_warn(&h->pdev->dev, HPSA "%d: a power on " - "or device reset detected\n", h->ctlr); + dev_warn(&h->pdev->dev, + "%s: a power on or device reset detected\n", + h->devname); break; case UNIT_ATTENTION_CLEARED: - dev_warn(&h->pdev->dev, HPSA "%d: unit attention " - "cleared by another initiator\n", h->ctlr); + dev_warn(&h->pdev->dev, + "%s: unit attention cleared by another initiator\n", + h->devname); break; default: - dev_warn(&h->pdev->dev, HPSA "%d: unknown " - "unit attention detected\n", h->ctlr); + dev_warn(&h->pdev->dev, + "%s: unknown unit attention detected\n", + h->devname); break; } return 1; @@ -4799,22 +4802,16 @@ static int hpsa_scan_finished(struct Scsi_Host *sh, return finished; } -static void hpsa_unregister_scsi(struct ctlr_info *h) -{ - /* we are being forcibly unloaded, and may not refuse. */ - scsi_remove_host(h->scsi_host); - scsi_host_put(h->scsi_host); - h->scsi_host = NULL; -} - -static int hpsa_register_scsi(struct ctlr_info *h) +static int hpsa_scsi_host_alloc(struct ctlr_info *h) { struct Scsi_Host *sh; int error; sh = scsi_host_alloc(&hpsa_driver_template, sizeof(h)); - if (sh == NULL) - goto fail; + if (sh == NULL) { + dev_err(&h->pdev->dev, "scsi_host_alloc failed\n"); + return -ENOMEM; + } sh->io_port = 0; sh->n_io_port = 0; @@ -4826,7 +4823,6 @@ static int hpsa_register_scsi(struct ctlr_info *h) sh->can_queue = h->nr_cmds - HPSA_NRESERVED_CMDS; sh->cmd_per_lun = sh->can_queue; sh->sg_tablesize = h->maxsgentries; - h->scsi_host = sh; sh->hostdata[0] = (unsigned long) h; sh->irq = h->intr[h->intr_mode]; sh->unique_id = sh->irq; @@ -4835,24 +4831,24 @@ static int hpsa_register_scsi(struct ctlr_info *h) dev_err(&h->pdev->dev, "%s: scsi_init_shared_tag_map failed for controller %d\n", __func__, h->ctlr); - goto fail_host_put; - } - error = scsi_add_host(sh, &h->pdev->dev); - if (error) { - dev_err(&h->pdev->dev, "%s: scsi_add_host failed for controller %d\n", - __func__, h->ctlr); - goto fail_host_put; + scsi_host_put(sh); + return error; } - scsi_scan_host(sh); + h->scsi_host = sh; return 0; +} - fail_host_put: - scsi_host_put(sh); - return error; - fail: - dev_err(&h->pdev->dev, "%s: scsi_host_alloc" - " failed for controller %d\n", __func__, h->ctlr); - return -ENOMEM; +static int hpsa_scsi_add_host(struct ctlr_info *h) +{ + int rv; + + rv = scsi_add_host(h->scsi_host, &h->pdev->dev); + if (rv) { + dev_err(&h->pdev->dev, "scsi_add_host failed\n"); + return rv; + } + scsi_scan_host(h->scsi_host); +
[PATCH] libfc: abort an exchange in case of underrun error
Currently exchange is not aborted in case underrun, so this patch fixes this by issuing exchange abort along FC_DATA_UNDRUN error since such error-ed exchange must be aborted first before same can be re-used. Tested-By: Jack Morgan Signed-off-by: Vasu Dev --- drivers/scsi/libfc/fc_fcp.c |4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index c679594..9ad1248 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -959,8 +959,10 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp) if (fsp->cdb_status == SAM_STAT_GOOD && fsp->xfer_len < fsp->data_len && !fsp->io_status && (!(fsp->scsi_comp_flags & FCP_RESID_UNDER) || -fsp->xfer_len < fsp->data_len - fsp->scsi_resid)) +fsp->xfer_len < fsp->data_len - fsp->scsi_resid)) { fsp->status_code = FC_DATA_UNDRUN; + fc_fcp_send_abort(fsp); + } } seq = fsp->seq_ptr; -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: OOPS: unplugging western digital passport drive
On 03/11/2015 12:25 AM, Stanisław Pitucha wrote: > Hi linux-scsi, > I've got another case of reproducible crash when unplugging western > digital passport drives. This was mentioned before in > http://www.spinics.net/lists/linux-scsi/msg82603.html > > Is there any way I can get a more correct stacktrace of the original > bug without changing/recompiling the kernel? (or with?) > > My last log from oops is: > > [ 3343.469871]: usb 4-1: USB disconnect, device number 3 > [ 3343.521948]: BUG: unable to handle kernel NULL pointer dereference > at 01a0 > [ 3343.522052]: IP: [] blk_post_runtime_resume+0x65/0x80 > [ 3343.522131]: PGD 0 > [ 3343.522159]: Oops: 0002 [#1] PREEMPT SMP > [ 3343.522215]: Modules linked in: nls_utf8 hfsplus ses enclosure uas > usb_storage rfcomm fuse ctr ccm bnep ecb btusb bluetooth uvcvideo > videobuf2_vmalloc videobuf2_memops videobuf2_core v4l2_common videodev > joydev media mousedev iTCO_wdt iTCO_vendor_support arc4 coretemp > intel_rapl x86_pkg_temp_thermal intel_powerclamp iwldvm kvm_intel > mac80211 kvm evdev mac_hid psmouse serio_raw pcspkr snd_hda_codec_hdmi > iwlwifi snd_hda_codec_realtek i2c_i801 snd_hda_codec_generic > rtsx_pci_ms i915 snd_hda_intel memstick snd_hda_controller cfg80211 > snd_hda_codec r8169 snd_hwdep mii snd_pcm drm_kms_helper snd_timer > lpc_ich shpchp drm thinkpad_acpi intel_gtt i2c_algo_bit nvram mei_me > i2c_core snd mei soundcore led_class rfkill hwmon tpm_tis tpm battery > wmi thermal video button processor ac sch_fq_codel usbhid > hid_logitech_dj > [ 3343.523406]: hid_generic hid nfs lockd grace sunrpc fscache ext4 > crc16 mbcache jbd2 sha256_ssse3 sha256_generic algif_skcipher af_alg > dm_crypt dm_mod sr_mod cdrom sd_mod rtsx_pci_sdmmc atkbd mmc_core > libps2 crct10dif_pclmul crc32_pclmul crc32c_intel ghash_clmulni_intel > ahci libahci aesni_intel aes_x86_64 lrw gf128mul glue_helper > ablk_helper cryptd libata xhci_pci ehci_pci scsi_mod xhci_hcd ehci_hcd > rtsx_pci usbcore usb_common i8042 serio > [ 3343.523825]: CPU: 1 PID: 22490 Comm: kworker/1:0 Not tainted 3.18.6-1-ARCH > #1 > [ 3343.523882]: Hardware name: LENOVO 2481CTO/2481CTO, BIOS > G3ET36WW(1.10) 06/20/2012 > [ 3343.523953]: Workqueue: usb_hub_wq hub_event [usbcore] > [ 3343.523997]: task: 880211fd5080 ti: 8801971bc000 task.ti: > 8801971bc000 > [ 3343.524054]: RIP: 0010:[] [] > blk_post_runtime_resume+0x65/0x80 > [ 3343.524131]: RSP: 0018:8801971bf8c8 EFLAGS: 00010092 > [ 3343.524173]: RAX: RBX: 880211ca1698 RCX: > > [ 3343.524228]: RDX: 0001000dea0f RSI: 0009 RDI: > 880211ca1698 > [ 3343.524283]: RBP: 8801971bf8d8 R08: R09: > 880216c3f000 > [ 3343.524338]: R10: 88021f256db0 R11: ea0002987d40 R12: > > [ 3343.524392]: R13: R14: 88020df7b428 R15: > 0004 > [ 3343.524448]: FS: () GS:88021f24() > knlGS: > [ 3343.524509]: CS: 0010 DS: ES: CR0: 80050033 > [ 3343.524554]: CR2: 01a0 CR3: 01811000 CR4: > 001407e0 > [ 3343.524609]: Stack: > [ 3343.524628]: 8802123fe968 8801971bf908 > a0119564 > [ 3343.524695]: 8801971bf910 8802123fe968 8802123fea16 > a01194e0 > [ 3343.524762]: 8801971bf938 813c4636 8800a61f5780 > 8802123fe968 > [ 3343.524828]: Call Trace: > [ 3343.524866]: [] scsi_runtime_resume+0x84/0xd0 [scsi_mod] > [ 3343.524930]: [] ? > scsi_autopm_put_device+0x20/0x20 [scsi_mod] > [ 3343.524990]: [] __rpm_callback+0x36/0x90 > [ 3343.525035]: [] rpm_callback+0x26/0xa0 > [ 3343.525079]: [] rpm_resume+0x4b1/0x690 > [ 3343.525124]: [] __pm_runtime_resume+0x40/0x60 > [ 3343.525177]: [] __device_release_driver+0x29/0xf0 > [ 3343.525228]: [] device_release_driver+0x23/0x30 > [ 3343.525277]: [] bus_remove_device+0x108/0x180 > [ 3343.525325]: [] device_del+0x129/0x1f0 > [ 3343.525378]: [] __scsi_remove_device+0xcd/0xe0 > [scsi_mod] > [ 3343.525442]: [] scsi_forget_host+0x64/0x70 [scsi_mod] > [ 3343.525502]: [] scsi_remove_host+0x7b/0x130 [scsi_mod] > [ 3343.525558]: [] usb_stor_disconnect+0x59/0xd0 > [usb_storage] > [ 3343.525625]: [] usb_unbind_interface+0x1f8/0x2c0 > [usbcore] > [ 3343.525682]: [] ? rpm_idle+0x23/0x340 > [ 3343.525729]: [] __device_release_driver+0x7f/0xf0 > [ 3343.525779]: [] device_release_driver+0x23/0x30 > [ 3343.525828]: [] bus_remove_device+0x108/0x180 > [ 3343.525876]: [] device_del+0x129/0x1f0 > [ 3343.528574]: [] usb_disable_device+0x91/0x290 [usbcore] > [ 3343.531302]: [] usb_disconnect+0x94/0x2d0 [usbcore] > [ 3343.533981]: [] hub_event+0x66a/0x1640 [usbcore] > [ 3343.536657]: [] ? __schedule+0x3e8/0xa50 > [ 3343.539275]: [] process_one_work+0x145/0x400 > [ 3343.541919]: [] worker_thread+0x6b/0x480 > [ 3343.544524]: [] ? init_pwq.part.22+0x10/0x10 > [ 3343.547108]: [] kthread+0xea/0x100 > [ 3343.549708]: [
Re: iSCSI bug
I see the same problem. Would this help? Mar 17 21:13:00 storage1 kernel: [119260.960821] TARGET_CORE[iSCSI]: Detected NON_EXISTENT_LUN Access for 0x0090 Mar 17 21:13:00 storage1 kernel: [119260.963752] ABORT_TASK: Sending TMR_TASK_DOES_NOT_EXIST for ref_tag: 18170949 Mar 17 21:13:00 storage1 kernel: [119260.963759] ABORT_TASK: Sending TMR_TASK_DOES_NOT_EXIST for ref_tag: 18170948 Mar 17 21:13:00 storage1 kernel: [119260.963761] ABORT_TASK: Sending TMR_TASK_DOES_NOT_EXIST for ref_tag: 18170950 Mar 17 21:13:04 storage1 kernel: [119265.171082] Unexpected ret: -32 send data 48 Mar 17 21:13:06 storage1 kernel: [119267.172218] TARGET_CORE[iSCSI]: Detected NON_EXISTENT_LUN Access for 0x000a Mar 17 21:13:06 storage1 kernel: [119267.175296] ABORT_TASK: Sending TMR_TASK_DOES_NOT_EXIST for ref_tag: 182076996 Mar 17 21:13:06 storage1 kernel: [119267.175303] ABORT_TASK: Sending TMR_TASK_DOES_NOT_EXIST for ref_tag: 182076994 Mar 17 21:13:06 storage1 kernel: [119267.175306] ABORT_TASK: Sending TMR_TASK_DOES_NOT_EXIST for ref_tag: 182076997 Mar 17 21:13:07 storage1 kernel: [119267.796469] iSCSI Login timeout on Network Portal 10.12.9.249:3260 Mar 17 21:13:17 storage1 kernel: [119278.498259] NMI watchdog: BUG: soft lockup - CPU#1 stuck for 22s! [iscsi_trx:5637] Mar 17 21:13:17 storage1 kernel: [119278.501397] Modules linked in: ib_srpt(E) tcm_qla2xxx(E) tcm_loop(E) tcm_fc(E) iscsi_target_mod(E) target_core_user(E) uio(E) target_core_pscsi(E) target_core_file(E) target_core_iblock(E) target_core_mod(E) ib_cm(E) ib_sa(E) ib_mad(E) ib_core(E) ib_addr(E) qla2xxx(E) libfc(E) scsi_transport_fc(E) configfs(E) nfsd(E) auth_rpcgss(E) nfs_acl(E) nfs(E) lockd(E) grace(E) sunrpc(E) fscache(E) gpio_ich(E) amdkfd(E) amd_iommu_v2(E) coretemp(E) kvm_intel(E) kvm(E) radeon(E) serio_raw(E) 8021q(E) joydev(E) garp(E) ttm(E) mrp(E) stp(E) llc(E) drm_kms_helper(E) drm(E) lpc_ich(E) i7core_edac(E) edac_core(E) i5500_temp(E) ioatdma(E) 8250_fintek(E) mac_hid(E) shpchp(E) bonding(E) btrfs(E) raid456(E) async_raid6_recov(E) async_memcpy(E) bcache(E) async_pq(E) async_xor(E) raid10(E) async_tx(E) xor(E) raid6_pq(E) raid1(E) hid_generic(E) raid0(E) multipath(E) igb(E) mpt2sas(E) ixgbe(E) linear(E) raid_class(E) pata_acpi(E) i2c_algo_bit(E) dca(E) usbhid(E) scsi_transport_sas(E) hid(E) ahci(E) pata_jmicron(E) psmouse(E) mdio(E) ptp(E) libahci(E) pps_core(E) [last unloaded: target_core_mod] Mar 17 21:13:17 storage1 kernel: [119278.501476] CPU: 1 PID: 5637 Comm: iscsi_trx Tainted: GE 3.19.0-031900-generic #201502091451 Mar 17 21:13:17 storage1 kernel: [119278.501479] Hardware name: Supermicro X8DTN/X8DTN, BIOS 2.1c 10/28/2011 Mar 17 21:13:17 storage1 kernel: [119278.501481] task: 8808f86c2740 ti: 8808e7234000 task.ti: 8808e7234000 Mar 17 21:13:17 storage1 kernel: [119278.501484] RIP: 0010: [] [] iscsit_remove_cmd_from_immediate_queue+0x25/0x120 [iscsi_target_mod] Mar 17 21:13:17 storage1 kernel: [119278.501501] RSP: 0018:8808e7237ce8 EFLAGS: 0246 Mar 17 21:13:17 storage1 kernel: [119278.501503] RAX: 96da96da RBX: 0001 RCX: f9a9b4a6 Mar 17 21:13:17 storage1 kernel: [119278.501505] RDX: 96da RSI: 881081bbc800 RDI: 881081bbcbe8 Mar 17 21:13:17 storage1 kernel: [119278.501507] RBP: 8808e7237d08 R08: 880f45d68410 R09: 0101 Mar 17 21:13:17 storage1 kernel: [119278.501509] R10: 0001 R11: 001d R12: ff10 Mar 17 21:13:17 storage1 kernel: [119278.501511] R13: 8808e7237cd8 R14: 880f45d68350 R15: f9ac4872 Mar 17 21:13:17 storage1 kernel: [119278.501513] FS: () GS:88091bc2() knlGS: Mar 17 21:13:17 storage1 kernel: [119278.501516] CS: 0010 DS: ES: CR0: 8005003b Mar 17 21:13:17 storage1 kernel: [119278.501518] CR2: 012bb100 CR3: 01c15000 CR4: 07e0 Mar 17 21:13:17 storage1 kernel: [119278.501520] Stack: Mar 17 21:13:17 storage1 kernel: [119278.501521] 880f45d68140 881081bbc800 0001 880f45d68350 Mar 17 21:13:17 storage1 kernel: [119278.501525] 8808e7237d38 c0984230 c098d30b 880f45d68140 Mar 17 21:13:17 storage1 kernel: [119278.501528] 0001 0001 8808e7237d78 c098433e Mar 17 21:13:17 storage1 kernel: [119278.501531] Call Trace: Mar 17 21:13:17 storage1 kernel: [119278.501545] [] __iscsit_free_cmd+0x50/0xa0 [iscsi_target_mod] Mar 17 21:13:17 storage1 kernel: [119278.501557] [] ? iscsit_close_connection+0x3ab/0x640 [iscsi_target_mod] Mar 17 21:13:17 storage1 kernel: [119278.501568] [] iscsit_free_cmd+0xbe/0x160 [iscsi_target_mod] Mar 17 21:13:17 storage1 kernel: [119278.501580] [] iscsit_close_connection+0x3c4/0x640 [iscsi_target_mod] Mar 17 21:13:17 storage1 kernel: [119278.501590] [] iscsit_take_action_for_connection_exit+0x83/0x110 [iscsi_target_mod] Mar 17 21:13:17 storag