Message ID | 307F48E420013C4E85C75C93E532197AB809204C@BBYEXM01.pmc-sierra.internal (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 03/17/2015 04:27 PM, Achim Leubner wrote: > Reviewed-by: Achim Leubner <Achim.Leubner@pmcs.com> > > > -----Original Message----- > From: Mahesh Rajashekhara > Sent: Wednesday, March 4, 2015 9:39 AM > To: JBottomley@Parallels.com; linux-scsi@vger.kernel.org > Cc: aacraid@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 <Mahesh.Rajashekhara@pmcs.com> > --- > 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) Garbled patch? > 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; > + Wrong indentation. > + /* "ADAPTEC " for adaptec */ > + memcpy(VPDPage83Data.IdDescriptorType1.VendId, "ADAPTEC ", > + sizeof(VPDPage83Data.IdDescriptorType1.VendId)); > + memcpy(VPDPage83Data.IdDescriptorType1.ProductId, "ARRAY ", > + sizeof(VPDPage83Data.IdDescriptorType1.ProductId)); > + > + /* Convert to ascii based serial number. > + * The LSB is the the end. > + */ > + for (i = 0; i < 8; i++) { > + u8 temp = (u8)((get_serial_reply->uid >> ((7 - i) * 4)) & 0xF); > + if (temp > 0x9) { > + VPDPage83Data.IdDescriptorType1.SerialNumber[i] = 'A' + (temp - 0xA); > + } else { > + VPDPage83Data.IdDescriptorType1.SerialNumber[i] = '0' + temp; > + } > + } > + > + /* EUI-64 Vendor Identifier Field Format, > + * 24 bits for VendId and 40 bits for SN. > + */ > + /* VpdCodeSetBinary */ > + VPDPage83Data.IdDescriptorType2.CodeSet = 1; > + /* VpdIdentifierTypeEUI64 */ > + VPDPage83Data.IdDescriptorType2.IdentifierType = 2; > + VPDPage83Data.IdDescriptorType2.IdentifierLength = > +sizeof(VPDPage83Data.IdDescriptorType2) - 4; > + Same here. > + /* 0x0000055 for IBM, 0x0000D0 for Adaptec */ Do you ever use the IBM Vendor ID? If not, why do you mention it here? > + VPDPage83Data.IdDescriptorType2.EU64Id.VendId[0] = 0xD0; > + VPDPage83Data.IdDescriptorType2.EU64Id.VendId[1] = 0; > + VPDPage83Data.IdDescriptorType2.EU64Id.VendId[2] = 0; > + > + VPDPage83Data.IdDescriptorType2.EU64Id.Serial = get_serial_reply->uid; > + VPDPage83Data.IdDescriptorType2.EU64Id.Reserved = 0; > + > + /* Move the inquiry data to the response buffer. */ > + scsi_sg_copy_from_buffer(scsicmd, &VPDPage83Data, > + sizeof(VPDPage83Data)); > + } else { > + /* It must be for VPD 0x80 */ > + 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)); > + } > } > > scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; @@ -2302,9 +2411,10 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) > INQD_PDT_PROC : INQD_PDT_DA; > if (scsicmd->cmnd[2] == 0) { > /* supported vital product data pages */ > - arr[3] = 2; > + arr[3] = 3; > arr[4] = 0x0; > arr[5] = 0x80; > + arr[6] = 0x83; > arr[1] = scsicmd->cmnd[2]; > scsi_sg_copy_from_buffer(scsicmd, &inq_data, > sizeof(inq_data)); > @@ -2323,6 +2433,16 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) > /* SLES 10 SP1 special */ Gods. Are we still in there? I guess it's time to remove that, at least the comment ... > scsicmd->result = DID_OK << 16 | > COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; > + } else if (scsicmd->cmnd[2] == 0x83) { > + /* vpd page 0x83 - Device Identification Page */ > + char *sno = (char *)&inq_data; > + sno[3] = setinqserial(dev, &sno[4], > + scmd_id(scsicmd)); > + if (aac_wwn != 2) > + return aac_get_container_serial( > + scsicmd); > + scsicmd->result = DID_OK << 16 | > + COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; > } else { > /* vpd page not implemented */ > scsicmd->result = DID_OK << 16 | > @@ -2468,6 +2588,15 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) > mpd.bd.block_length[0] = (fsa_dev_ptr[cid].block_size >> 16) & 0xff; > mpd.bd.block_length[1] = (fsa_dev_ptr[cid].block_size >> 8) & 0xff; > mpd.bd.block_length[2] = fsa_dev_ptr[cid].block_size & 0xff; > + > + mpd.mpc_buf[0] = scsicmd->cmnd[2]; > + if (scsicmd->cmnd[2] == 0x1C) { > + mpd.mpc_buf[1] = 0xa; /* page length */ > + mpd.hd.data_length = 23; /* Mode data length */ > + } else { > + mpd.hd.data_length = 15; /* Mode data length */ > + } > + > if (capacity > 0xffffff) { > mpd.bd.block_count[0] = 0xff; > mpd.bd.block_count[1] = 0xff; > @@ -2486,9 +2615,12 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) > mpd.mpc_buf[2] = ((aac_cache & 6) == 2) > ? 0 : 0x04; /* WCE */ > mode_buf_length = sizeof(mpd); > - if (mode_buf_length > scsicmd->cmnd[4]) > - mode_buf_length = scsicmd->cmnd[4]; > } > + > + if (mode_buf_length > scsicmd->cmnd[4]) > + mode_buf_length = scsicmd->cmnd[4]; > + else > + mode_buf_length = sizeof(mpd); > scsi_sg_copy_from_buffer(scsicmd, (char *)&mpd, mode_buf_length); > scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; > scsicmd->scsi_done(scsicmd); > diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index c162a65..a37762e 100644 > --- a/drivers/scsi/aacraid/aacraid.h > +++ b/drivers/scsi/aacraid/aacraid.h > @@ -1015,6 +1015,7 @@ struct aac_supplement_adapter_info > #define AAC_OPTION_POWER_MANAGEMENT cpu_to_le32(0x00000004) > #define AAC_OPTION_DOORBELL_RESET cpu_to_le32(0x00004000) > #define AAC_OPTION_VARIABLE_BLOCK_SIZE cpu_to_le32(0x00040000) /* 4KB sector size */ > +#define AAC_OPTION_SUPPORTED_240_VOLUMES cpu_to_le32(0x10000000) > #define AAC_SIS_VERSION_V3 3 > #define AAC_SIS_SLOT_UNKNOWN 0xFF > > @@ -1212,11 +1213,13 @@ struct aac_dev > int sync_mode; > struct fib *sync_fib; > struct list_head sync_fib_list; > + u32 doorbell_mask; /* from GET_ADAPTER_PROP */ > u32 max_msix; /* max. MSI-X vectors */ > u32 vector_cap; /* MSI-X vector capab.*/ > int msi_enabled; /* MSI/MSI-X enabled */ > struct msix_entry msixentry[AAC_MAX_MSIX]; > struct aac_msix_ctx aac_msix[AAC_MAX_MSIX]; /* context */ > + u8 adapter_shutdown; > }; > > #define aac_adapter_interrupt(dev) \ > @@ -1749,6 +1752,7 @@ struct aac_get_container_count_resp { > __le32 MaxContainers; > __le32 ContainerSwitchEntries; > __le32 MaxPartitions; > + __le32 MaxSimpleVolumes; > }; > > What exactly has this to do with VPD page support? Please split if off into a separate patch. > diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 29c35c8..c3e13ae 100644 > --- a/drivers/scsi/aacraid/comminit.c > +++ b/drivers/scsi/aacraid/comminit.c > @@ -53,7 +53,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co { > unsigned char *base; > unsigned long size, align; > - const unsigned long fibsize = 4096; > + const unsigned long fibsize = dev->max_fib_size; > const unsigned long printfbufsiz = 256; > unsigned long host_rrq_size = 0; > struct aac_init *init; > @@ -230,6 +230,7 @@ int aac_send_shutdown(struct aac_dev * dev) > /* FIB should be freed only after getting the response from the F/W */ > if (status != -ERESTARTSYS) > aac_fib_free(fibctx); > + dev->adapter_shutdown = 1; > if ((dev->pdev->device == PMC_DEVICE_S7 || > dev->pdev->device == PMC_DEVICE_S8 || > dev->pdev->device == PMC_DEVICE_S9) && @@ -357,8 +358,9 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) > dev->raw_io_interface = dev->raw_io_64 = 0; > > if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES, > - 0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) && > + 0, 0, 0, 0, 0, 0, status+0, status+1, status+2, status+3, NULL)) && > (status[0] == 0x00000001)) { > + dev->doorbell_mask = status[3]; > if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_64)) > dev->raw_io_64 = 1; > dev->sync_mode = aac_sync_mode; > @@ -397,6 +399,7 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) > } > dev->max_msix = 0; > dev->msi_enabled = 0; > + dev->adapter_shutdown = 0; > if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS, > 0, 0, 0, 0, 0, 0, > status+0, status+1, status+2, status+3, status+4)) @@ -508,6 +511,7 @@ static void aac_define_int_mode(struct aac_dev *dev) > > int i, msi_count; > > + msi_count = i = 0; > /* max. vectors from GET_COMM_PREFERRED_SETTINGS */ > if (dev->max_msix == 0 || > dev->pdev->device == PMC_DEVICE_S6 || diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 83c5d3f..2bed445 100644 > --- a/drivers/scsi/aacraid/commsup.c > +++ b/drivers/scsi/aacraid/commsup.c > @@ -208,14 +208,11 @@ struct fib *aac_fib_alloc(struct aac_dev *dev) > > void aac_fib_free(struct fib *fibptr) > { > - unsigned long flags, flagsv; > + unsigned long flags; > > - spin_lock_irqsave(&fibptr->event_lock, flagsv); > if (fibptr->done == 2) { > - spin_unlock_irqrestore(&fibptr->event_lock, flagsv); > return; > } > - spin_unlock_irqrestore(&fibptr->event_lock, flagsv); > > spin_lock_irqsave(&fibptr->dev->fib_lock, flags); > if (unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) @@ -775,7 +772,6 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) > > int aac_fib_complete(struct fib *fibptr) { > - unsigned long flags; > struct hw_fib * hw_fib = fibptr->hw_fib_va; > > /* > @@ -798,12 +794,6 @@ int aac_fib_complete(struct fib *fibptr) > * command is complete that we had sent to the adapter and this > * cdb could be reused. > */ > - spin_lock_irqsave(&fibptr->event_lock, flags); > - if (fibptr->done == 2) { > - spin_unlock_irqrestore(&fibptr->event_lock, flags); > - return 0; > - } > - spin_unlock_irqrestore(&fibptr->event_lock, flags); > > if((hw_fib->header.XferState & cpu_to_le32(SentFromHost)) && > (hw_fib->header.XferState & cpu_to_le32(AdapterProcessed))) diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 7813a9b..4c5ba9e 100644 > --- a/drivers/scsi/aacraid/linit.c > +++ b/drivers/scsi/aacraid/linit.c > @@ -56,7 +56,7 @@ > > #include "aacraid.h" > > -#define AAC_DRIVER_VERSION "1.2-0" > +#define AAC_DRIVER_VERSION "1.2-1" > #ifndef AAC_DRIVER_BRANCH > #define AAC_DRIVER_BRANCH "" > #endif > @@ -65,7 +65,7 @@ > #ifdef AAC_DRIVER_BUILD > #define _str(x) #x > #define str(x) _str(x) > -#define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION "[" str(AAC_DRIVER_BUILD) "]" AAC_DRIVER_BRANCH > +#define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION "." str(AAC_DRIVER_BUILD) "" AAC_DRIVER_BRANCH > #else > #define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION AAC_DRIVER_BRANCH > #endif > @@ -253,19 +253,7 @@ static struct aac_driver_ident aac_drivers[] = { > > static int aac_queuecommand_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { > - struct Scsi_Host *host = cmd->device->host; > - struct aac_dev *dev = (struct aac_dev *)host->hostdata; > - u32 count = 0; > cmd->scsi_done = done; > - for (; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) { > - struct fib * fib = &dev->fibs[count]; > - struct scsi_cmnd * command; > - if (fib->hw_fib_va->header.XferState && > - ((command = fib->callback_data)) && > - (command == cmd) && > - (cmd->SCp.phase == AAC_OWNER_FIRMWARE)) > - return 0; /* Already owned by Adapter */ > - } > cmd->SCp.phase = AAC_OWNER_LOWLEVEL; > return (aac_scsi_cmd(cmd) ? FAILED : 0); } @@ -713,7 +701,9 @@ static long aac_cfg_ioctl(struct file *file, > unsigned int cmd, unsigned long arg) > { > int ret; > - if (!capable(CAP_SYS_RAWIO)) > + struct aac_dev *aac; > + aac = (struct aac_dev *)file->private_data; > + if (!capable(CAP_SYS_RAWIO) || aac->adapter_shutdown) > return -EPERM; > mutex_lock(&aac_mutex); > ret = aac_do_ioctl(file->private_data, cmd, (void __user *)arg); diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c index c010248..82ff025 100644 > --- a/drivers/scsi/aacraid/src.c > +++ b/drivers/scsi/aacraid/src.c > @@ -200,6 +200,7 @@ static int src_sync_cmd(struct aac_dev *dev, u32 command, > u32 *status, u32 * r1, u32 * r2, u32 * r3, u32 * r4) { > unsigned long start; > + unsigned long delay; > int ok; > > /* > @@ -240,10 +241,15 @@ static int src_sync_cmd(struct aac_dev *dev, u32 command, > ok = 0; > start = jiffies; > > - /* > - * Wait up to 5 minutes > - */ > - while (time_before(jiffies, start+300*HZ)) { > + if (command == IOP_RESET_ALWAYS) { > + /* Wait up to 10 sec */ > + delay = 10*HZ; > + } else { > + /* Wait up to 5 minutes */ > + delay = 300*HZ; > + } > + while (time_before(jiffies, start+delay)) { > + > udelay(5); /* Delay 5 microseconds to let Mon960 get info. */ > /* > * Mon960 will set doorbell0 bit when it has completed the command. > @@ -562,10 +568,16 @@ static int aac_src_restart_adapter(struct aac_dev *dev, int bled) > if (bled) > printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n", > dev->name, dev->id, bled); > + dev->a_ops.adapter_enable_int = aac_src_disable_interrupt; > bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, > 0, 0, 0, 0, 0, 0, &var, &reset_mask, NULL, NULL, NULL); > - if (bled || (var != 0x00000001)) > + if ((bled || (var != 0x00000001)) && !dev->doorbell_mask) > return -EINVAL; > + else if (dev->doorbell_mask) { > + reset_mask = dev->doorbell_mask; > + bled = 0; > + var = 0x00000001; > + } > > if ((dev->pdev->device == PMC_DEVICE_S7 || > dev->pdev->device == PMC_DEVICE_S8 || @@ -575,10 +587,13 @@ static int aac_src_restart_adapter(struct aac_dev *dev, int bled) > msleep(5000); /* Delay 5 seconds */ > } > > - if (dev->supplement_adapter_info.SupportedOptions2 & > - AAC_OPTION_DOORBELL_RESET) { > + if (!bled && (dev->supplement_adapter_info.SupportedOptions2 & > + AAC_OPTION_DOORBELL_RESET)) { > src_writel(dev, MUnit.IDR, reset_mask); > ssleep(45); > + } else { > + src_writel(dev, MUnit.IDR, 0x100); > + ssleep(45); > } > } > > @@ -600,7 +615,6 @@ int aac_src_select_comm(struct aac_dev *dev, int comm) { > switch (comm) { > case AAC_COMM_MESSAGE: > - dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message; > dev->a_ops.adapter_intr = aac_src_intr_message; > dev->a_ops.adapter_deliver = aac_src_deliver_message; > break; > @@ -698,6 +712,7 @@ int aac_src_init(struct aac_dev *dev) > */ > dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter; > dev->a_ops.adapter_disable_int = aac_src_disable_interrupt; > + dev->a_ops.adapter_enable_int = aac_src_disable_interrupt; > dev->a_ops.adapter_notify = aac_src_notify_adapter; > dev->a_ops.adapter_sync_cmd = src_sync_cmd; > dev->a_ops.adapter_check_health = aac_src_check_health; @@ -735,6 +750,7 @@ int aac_src_init(struct aac_dev *dev) > dev->dbg_base = pci_resource_start(dev->pdev, 2); > dev->dbg_base_mapped = dev->regs.src.bar1; > dev->dbg_size = AAC_MIN_SRC_BAR1_SIZE; > + dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message; > > aac_adapter_enable_int(dev); > > @@ -861,6 +877,7 @@ int aac_srcv_init(struct aac_dev *dev) > */ > dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter; > dev->a_ops.adapter_disable_int = aac_src_disable_interrupt; > + dev->a_ops.adapter_enable_int = aac_src_disable_interrupt; > dev->a_ops.adapter_notify = aac_src_notify_adapter; > dev->a_ops.adapter_sync_cmd = src_sync_cmd; > dev->a_ops.adapter_check_health = aac_src_check_health; @@ -913,6 +930,7 @@ int aac_srcv_init(struct aac_dev *dev) > dev->dbg_base = dev->base_start; > dev->dbg_base_mapped = dev->base; > dev->dbg_size = dev->base_size; > + dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message; > > aac_adapter_enable_int(dev); > > -- > 1.7.7.3 > Please split off the unrelated bits into a separate patch. Otherwise tracking and regression testing becomes really hard. Cheers, Hannes
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.IdDescriptorType1.VendId, "ADAPTEC ", + sizeof(VPDPage83Data.IdDescriptorType1.VendId)); + memcpy(VPDPage83Data.IdDescriptorType1.ProductId, "ARRAY ", + sizeof(VPDPage83Data.IdDescriptorType1.ProductId)); + + /* Convert to ascii based serial number. + * The LSB is the the end. + */ + for (i = 0; i < 8; i++) { + u8 temp = (u8)((get_serial_reply->uid >> ((7 - i) * 4)) & 0xF); + if (temp > 0x9) { + VPDPage83Data.IdDescriptorType1.SerialNumber[i] = 'A' + (temp - 0xA); + } else { + VPDPage83Data.IdDescriptorType1.SerialNumber[i] = '0' + temp; + } + } + + /* EUI-64 Vendor Identifier Field Format, + * 24 bits for VendId and 40 bits for SN. + */ + /* VpdCodeSetBinary */ + VPDPage83Data.IdDescriptorType2.CodeSet = 1; + /* VpdIdentifierTypeEUI64 */ + VPDPage83Data.IdDescriptorType2.IdentifierType = 2; + VPDPage83Data.IdDescriptorType2.IdentifierLength = +sizeof(VPDPage83Data.IdDescriptorType2) - 4; + + /* 0x0000055 for IBM, 0x0000D0 for Adaptec */ + VPDPage83Data.IdDescriptorType2.EU64Id.VendId[0] = 0xD0; + VPDPage83Data.IdDescriptorType2.EU64Id.VendId[1] = 0; + VPDPage83Data.IdDescriptorType2.EU64Id.VendId[2] = 0; + + VPDPage83Data.IdDescriptorType2.EU64Id.Serial = get_serial_reply->uid; + VPDPage83Data.IdDescriptorType2.EU64Id.Reserved = 0; + + /* Move the inquiry data to the response buffer. */ + scsi_sg_copy_from_buffer(scsicmd, &VPDPage83Data, + sizeof(VPDPage83Data)); + } else { + /* It must be for VPD 0x80 */ + 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)); + } } scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; @@ -2302,9 +2411,10 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) INQD_PDT_PROC : INQD_PDT_DA; if (scsicmd->cmnd[2] == 0) { /* supported vital product data pages */ - arr[3] = 2; + arr[3] = 3; arr[4] = 0x0; arr[5] = 0x80; + arr[6] = 0x83; arr[1] = scsicmd->cmnd[2]; scsi_sg_copy_from_buffer(scsicmd, &inq_data, sizeof(inq_data)); @@ -2323,6 +2433,16 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) /* SLES 10 SP1 special */ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; + } else if (scsicmd->cmnd[2] == 0x83) { + /* vpd page 0x83 - Device Identification Page */ + char *sno = (char *)&inq_data; + sno[3] = setinqserial(dev, &sno[4], + scmd_id(scsicmd)); + if (aac_wwn != 2) + return aac_get_container_serial( + scsicmd); + scsicmd->result = DID_OK << 16 | + COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; } else { /* vpd page not implemented */ scsicmd->result = DID_OK << 16 | @@ -2468,6 +2588,15 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) mpd.bd.block_length[0] = (fsa_dev_ptr[cid].block_size >> 16) & 0xff; mpd.bd.block_length[1] = (fsa_dev_ptr[cid].block_size >> 8) & 0xff; mpd.bd.block_length[2] = fsa_dev_ptr[cid].block_size & 0xff; + + mpd.mpc_buf[0] = scsicmd->cmnd[2]; + if (scsicmd->cmnd[2] == 0x1C) { + mpd.mpc_buf[1] = 0xa; /* page length */ + mpd.hd.data_length = 23; /* Mode data length */ + } else { + mpd.hd.data_length = 15; /* Mode data length */ + } + if (capacity > 0xffffff) { mpd.bd.block_count[0] = 0xff; mpd.bd.block_count[1] = 0xff; @@ -2486,9 +2615,12 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) mpd.mpc_buf[2] = ((aac_cache & 6) == 2) ? 0 : 0x04; /* WCE */ mode_buf_length = sizeof(mpd); - if (mode_buf_length > scsicmd->cmnd[4]) - mode_buf_length = scsicmd->cmnd[4]; } + + if (mode_buf_length > scsicmd->cmnd[4]) + mode_buf_length = scsicmd->cmnd[4]; + else + mode_buf_length = sizeof(mpd); scsi_sg_copy_from_buffer(scsicmd, (char *)&mpd, mode_buf_length); scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; scsicmd->scsi_done(scsicmd); diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index c162a65..a37762e 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -1015,6 +1015,7 @@ struct aac_supplement_adapter_info #define AAC_OPTION_POWER_MANAGEMENT cpu_to_le32(0x00000004) #define AAC_OPTION_DOORBELL_RESET cpu_to_le32(0x00004000) #define AAC_OPTION_VARIABLE_BLOCK_SIZE cpu_to_le32(0x00040000) /* 4KB sector size */ +#define AAC_OPTION_SUPPORTED_240_VOLUMES cpu_to_le32(0x10000000) #define AAC_SIS_VERSION_V3 3 #define AAC_SIS_SLOT_UNKNOWN 0xFF @@ -1212,11 +1213,13 @@ struct aac_dev int sync_mode; struct fib *sync_fib; struct list_head sync_fib_list; + u32 doorbell_mask; /* from GET_ADAPTER_PROP */ u32 max_msix; /* max. MSI-X vectors */ u32 vector_cap; /* MSI-X vector capab.*/ int msi_enabled; /* MSI/MSI-X enabled */ struct msix_entry msixentry[AAC_MAX_MSIX]; struct aac_msix_ctx aac_msix[AAC_MAX_MSIX]; /* context */ + u8 adapter_shutdown; }; #define aac_adapter_interrupt(dev) \ @@ -1749,6 +1752,7 @@ struct aac_get_container_count_resp { __le32 MaxContainers; __le32 ContainerSwitchEntries; __le32 MaxPartitions; + __le32 MaxSimpleVolumes; }; diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 29c35c8..c3e13ae 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -53,7 +53,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co { unsigned char *base; unsigned long size, align; - const unsigned long fibsize = 4096; + const unsigned long fibsize = dev->max_fib_size; const unsigned long printfbufsiz = 256; unsigned long host_rrq_size = 0; struct aac_init *init; @@ -230,6 +230,7 @@ int aac_send_shutdown(struct aac_dev * dev) /* FIB should be freed only after getting the response from the F/W */ if (status != -ERESTARTSYS) aac_fib_free(fibctx); + dev->adapter_shutdown = 1; if ((dev->pdev->device == PMC_DEVICE_S7 || dev->pdev->device == PMC_DEVICE_S8 || dev->pdev->device == PMC_DEVICE_S9) && @@ -357,8 +358,9 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) dev->raw_io_interface = dev->raw_io_64 = 0; if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES, - 0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) && + 0, 0, 0, 0, 0, 0, status+0, status+1, status+2, status+3, NULL)) && (status[0] == 0x00000001)) { + dev->doorbell_mask = status[3]; if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_64)) dev->raw_io_64 = 1; dev->sync_mode = aac_sync_mode; @@ -397,6 +399,7 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) } dev->max_msix = 0; dev->msi_enabled = 0; + dev->adapter_shutdown = 0; if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS, 0, 0, 0, 0, 0, 0, status+0, status+1, status+2, status+3, status+4)) @@ -508,6 +511,7 @@ static void aac_define_int_mode(struct aac_dev *dev) int i, msi_count; + msi_count = i = 0; /* max. vectors from GET_COMM_PREFERRED_SETTINGS */ if (dev->max_msix == 0 || dev->pdev->device == PMC_DEVICE_S6 || diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 83c5d3f..2bed445 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -208,14 +208,11 @@ struct fib *aac_fib_alloc(struct aac_dev *dev) void aac_fib_free(struct fib *fibptr) { - unsigned long flags, flagsv; + unsigned long flags; - spin_lock_irqsave(&fibptr->event_lock, flagsv); if (fibptr->done == 2) { - spin_unlock_irqrestore(&fibptr->event_lock, flagsv); return; } - spin_unlock_irqrestore(&fibptr->event_lock, flagsv); spin_lock_irqsave(&fibptr->dev->fib_lock, flags); if (unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) @@ -775,7 +772,6 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) int aac_fib_complete(struct fib *fibptr) { - unsigned long flags; struct hw_fib * hw_fib = fibptr->hw_fib_va; /* @@ -798,12 +794,6 @@ int aac_fib_complete(struct fib *fibptr) * command is complete that we had sent to the adapter and this * cdb could be reused. */ - spin_lock_irqsave(&fibptr->event_lock, flags); - if (fibptr->done == 2) { - spin_unlock_irqrestore(&fibptr->event_lock, flags); - return 0; - } - spin_unlock_irqrestore(&fibptr->event_lock, flags); if((hw_fib->header.XferState & cpu_to_le32(SentFromHost)) && (hw_fib->header.XferState & cpu_to_le32(AdapterProcessed))) diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 7813a9b..4c5ba9e 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -56,7 +56,7 @@ #include "aacraid.h" -#define AAC_DRIVER_VERSION "1.2-0" +#define AAC_DRIVER_VERSION "1.2-1" #ifndef AAC_DRIVER_BRANCH #define AAC_DRIVER_BRANCH "" #endif @@ -65,7 +65,7 @@ #ifdef AAC_DRIVER_BUILD #define _str(x) #x #define str(x) _str(x) -#define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION "[" str(AAC_DRIVER_BUILD) "]" AAC_DRIVER_BRANCH +#define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION "." str(AAC_DRIVER_BUILD) "" AAC_DRIVER_BRANCH #else #define AAC_DRIVER_FULL_VERSION AAC_DRIVER_VERSION AAC_DRIVER_BRANCH #endif @@ -253,19 +253,7 @@ static struct aac_driver_ident aac_drivers[] = { static int aac_queuecommand_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { - struct Scsi_Host *host = cmd->device->host; - struct aac_dev *dev = (struct aac_dev *)host->hostdata; - u32 count = 0; cmd->scsi_done = done; - for (; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) { - struct fib * fib = &dev->fibs[count]; - struct scsi_cmnd * command; - if (fib->hw_fib_va->header.XferState && - ((command = fib->callback_data)) && - (command == cmd) && - (cmd->SCp.phase == AAC_OWNER_FIRMWARE)) - return 0; /* Already owned by Adapter */ - } cmd->SCp.phase = AAC_OWNER_LOWLEVEL; return (aac_scsi_cmd(cmd) ? FAILED : 0); } @@ -713,7 +701,9 @@ static long aac_cfg_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret; - if (!capable(CAP_SYS_RAWIO)) + struct aac_dev *aac; + aac = (struct aac_dev *)file->private_data; + if (!capable(CAP_SYS_RAWIO) || aac->adapter_shutdown) return -EPERM; mutex_lock(&aac_mutex); ret = aac_do_ioctl(file->private_data, cmd, (void __user *)arg); diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c index c010248..82ff025 100644 --- a/drivers/scsi/aacraid/src.c +++ b/drivers/scsi/aacraid/src.c @@ -200,6 +200,7 @@ static int src_sync_cmd(struct aac_dev *dev, u32 command, u32 *status, u32 * r1, u32 * r2, u32 * r3, u32 * r4) { unsigned long start; + unsigned long delay; int ok; /* @@ -240,10 +241,15 @@ static int src_sync_cmd(struct aac_dev *dev, u32 command,