James, Any Feedback on this patch? ~ Kashyap > -----Original Message----- > From: linux-scsi-owner@xxxxxxxxxxxxxxx [mailto:linux-scsi- > owner@xxxxxxxxxxxxxxx] On Behalf Of Kashyap, Desai > Sent: Thursday, April 07, 2011 12:33 PM > To: linux-scsi@xxxxxxxxxxxxxxx > Cc: James.Bottomley@xxxxxxxxxxxxxxxxxxxxx; Moore, Eric; Prakash, Sathya > Subject: [PATCH] [Resend with git format] mpt2sas : WarpDrive New > product SSS6200 support added > > > [Please Ignore earlier partch.] > [Resending this patch in git diff format. Earlier patch was not in git > diff format.] > > > Introduction > This patch has > Support for the new solid state device product SSS6200 from LSI and > relavent > features w.r.t SSS6200. > > The major feature added in this driver is supporting Direct-I/O to the > SSS6200 storage.There are some additional changes done to avoid > exposing > the RAID member disks to the OS and hiding/exposing drives based on the > OEM Specific Flag in Manufacturing Page10 (this is required to handle > specific changes in the SSS6200 firmware). > > Each and every changes are listed below. > 1. Hiding IR related messages. > For SSS6200, the driver is modified not to print IR related events. > Even if the debugging is enabled the IR related messages will not be > displayed. > In some places if there is a need to display a message related to IR > the > string "IR" is replaced with string "DD" and the string "volume" is > replaced > with "direct drive". But the function names are not changed hence there > are > some places where the reference to volume can be seen if debug level is > set. > > 2. Removed RAID transport support > In Linux the user can retrieve RAID volume information from the sysfs > directory. > This support is removed for SSS6200. > > 3. Direct I/O support. > The driver tries to enable direct I/O when a volume is reported to the > driver > by the firmware through IRCC events and the driver does this just > before > reporting to the OS, hence all the OS issued I/O can go through direct > path > if they can, The first validation is to see whether the manufacturing > page10 > flag is set to expose all drives always. If that is set, the driver > will not > enable direct I/O and displays the message "DDIO" is disabled globally > as > drives are exposed. The driver checks whether there is more than one > volume > in the controller, if so the direct I/O will be disabled globally for > all > volumes in the controller and the message displayed will be "DDIO is > disabled > globally as number of drives > 1. > If retrieving number of PD is failed the driver will not enable direct > I/O > and displays the message Failure in computing number of drives DDIO > disabled. > If memory allocation for RAIDVolumePage0 is failed, the driver will not > enable > direct I/O and displays the message Memory allocation failure for > RVPG0 DDIO disabled. If retrieving RAIDVolumePage0 is failed the > driver will > not enable direct I/O and displays the message Failure in retrieving > RVPG0 DDIO disabled > > If the number of PD in a volume is greater than 8, then the direct I/O > will > be disabled. > If any of individual drives handle retrieval is failed then the DD-IO > will > be disabled. > If the volume is not RAID0 or if the block size is not 512 then the DD- > IO will > be disabled. > If the volume size is greater than 2TB then the DD-IO will be disabled. > If the driver is not able to find a valid stripe exponent using the > configured > stripe size then the DD-IO will be disabled > > When the DD-IO is enabled the driver will check every I/O request > issued to > the storage and checks whether the request is either > READ6/WRITE6/READ10/WRITE10, if it is and if the complete I/O transfer > is within a stripe size then the I/O is redirected to > the drive directly instead of the volume. > > On completion of every I/O, if the completion is failure means if the > reply > is address reply with a reply frame associated with it, then the type > of I/O > will be checked, if the I/O is direct then the I/O will be retried to > the volume once. > > Signed-off-by: Kashyap Desai <kashyap.desai@xxxxxxx> > Reviewed-by: Eric Moore <eric.moore@xxxxxxx> > Reviewed-by: Sathya Prakash <sathya.prakash@xxxxxxx> > --- > diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c > b/drivers/scsi/mpt2sas/mpt2sas_base.c > index 5e001ff..e80015d 100644 > --- a/drivers/scsi/mpt2sas/mpt2sas_base.c > +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c > @@ -522,7 +522,8 @@ _base_display_event_data(struct MPT2SAS_ADAPTER > *ioc, > desc = "Device Status Change"; > break; > case MPI2_EVENT_IR_OPERATION_STATUS: > - desc = "IR Operation Status"; > + if (!ioc->hide_ir_msg) > + desc = "IR Operation Status"; > break; > case MPI2_EVENT_SAS_DISCOVERY: > { > @@ -553,16 +554,20 @@ _base_display_event_data(struct MPT2SAS_ADAPTER > *ioc, > desc = "SAS Enclosure Device Status Change"; > break; > case MPI2_EVENT_IR_VOLUME: > - desc = "IR Volume"; > + if (!ioc->hide_ir_msg) > + desc = "IR Volume"; > break; > case MPI2_EVENT_IR_PHYSICAL_DISK: > - desc = "IR Physical Disk"; > + if (!ioc->hide_ir_msg) > + desc = "IR Physical Disk"; > break; > case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: > - desc = "IR Configuration Change List"; > + if (!ioc->hide_ir_msg) > + desc = "IR Configuration Change List"; > break; > case MPI2_EVENT_LOG_ENTRY_ADDED: > - desc = "Log Entry Added"; > + if (!ioc->hide_ir_msg) > + desc = "Log Entry Added"; > break; > } > > @@ -616,7 +621,10 @@ _base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , > u32 log_info) > originator_str = "PL"; > break; > case 2: > - originator_str = "IR"; > + if (!ioc->hide_ir_msg) > + originator_str = "IR"; > + else > + originator_str = "WarpDrive"; > break; > } > > @@ -1508,6 +1516,7 @@ mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER > *ioc, u16 smid) > } > ioc->scsi_lookup[i].cb_idx = 0xFF; > ioc->scsi_lookup[i].scmd = NULL; > + ioc->scsi_lookup[i].direct_io = 0; > list_add_tail(&ioc->scsi_lookup[i].tracker_list, > &ioc->free_list); > spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); > @@ -1844,10 +1853,12 @@ _base_display_ioc_capabilities(struct > MPT2SAS_ADAPTER *ioc) > printk("), "); > printk("Capabilities=("); > > - if (ioc->facts.IOCCapabilities & > - MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) { > - printk("Raid"); > - i++; > + if (!ioc->hide_ir_msg) { > + if (ioc->facts.IOCCapabilities & > + MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) { > + printk("Raid"); > + i++; > + } > } > > if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR) { > @@ -3680,6 +3691,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER > *ioc, int sleep_flag) > u32 reply_address; > u16 smid; > struct _tr_list *delayed_tr, *delayed_tr_next; > + u8 hide_flag; > > dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, > __func__)); > @@ -3706,6 +3718,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER > *ioc, int sleep_flag) > ioc->scsi_lookup[i].cb_idx = 0xFF; > ioc->scsi_lookup[i].smid = smid; > ioc->scsi_lookup[i].scmd = NULL; > + ioc->scsi_lookup[i].direct_io = 0; > list_add_tail(&ioc->scsi_lookup[i].tracker_list, > &ioc->free_list); > } > @@ -3766,6 +3779,15 @@ _base_make_ioc_operational(struct > MPT2SAS_ADAPTER *ioc, int sleep_flag) > if (sleep_flag == CAN_SLEEP) > _base_static_config_pages(ioc); > > + if (ioc->wait_for_port_enable_to_complete && ioc->is_warpdrive) { > + if (ioc->manu_pg10.OEMIdentifier == 0x80) { > + hide_flag = (u8) (ioc->manu_pg10.OEMSpecificFlags0 & > + MFG_PAGE10_HIDE_SSDS_MASK); > + if (hide_flag != MFG_PAGE10_HIDE_SSDS_MASK) > + ioc->mfg_pg10_hide_flag = hide_flag; > + } > + } > + > if (ioc->wait_for_port_enable_to_complete) { > if (diag_buffer_enable != 0) > mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable); > diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h > b/drivers/scsi/mpt2sas/mpt2sas_base.h > index 5003282..2a3c05f 100644 > --- a/drivers/scsi/mpt2sas/mpt2sas_base.h > +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h > @@ -69,11 +69,11 @@ > #define MPT2SAS_DRIVER_NAME "mpt2sas" > #define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@xxxxxxx>" > #define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" > -#define MPT2SAS_DRIVER_VERSION "08.100.00.00" > +#define MPT2SAS_DRIVER_VERSION "08.100.00.01" > #define MPT2SAS_MAJOR_VERSION 08 > #define MPT2SAS_MINOR_VERSION 100 > #define MPT2SAS_BUILD_VERSION 00 > -#define MPT2SAS_RELEASE_VERSION 00 > +#define MPT2SAS_RELEASE_VERSION 01 > > /* > * Set MPT2SAS_SG_DEPTH value based on user input. > @@ -189,6 +189,16 @@ > #define MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID 0x0046 > > /* > + * WarpDrive Specific Log codes > + */ > + > +#define MPT2_WARPDRIVE_LOGENTRY (0x8002) > +#define MPT2_WARPDRIVE_LC_SSDT (0x41) > +#define MPT2_WARPDRIVE_LC_SSDLW (0x43) > +#define MPT2_WARPDRIVE_LC_SSDLF (0x44) > +#define MPT2_WARPDRIVE_LC_BRMF (0x4D) > + > +/* > * per target private data > */ > #define MPT_TARGET_FLAGS_RAID_COMPONENT 0x01 > @@ -199,6 +209,7 @@ > * struct MPT2SAS_TARGET - starget private hostdata > * @starget: starget object > * @sas_address: target sas address > + * @raid_device: raid_device pointer to access volume data > * @handle: device handle > * @num_luns: number luns > * @flags: MPT_TARGET_FLAGS_XXX flags > @@ -208,6 +219,7 @@ > struct MPT2SAS_TARGET { > struct scsi_target *starget; > u64 sas_address; > + struct _raid_device *raid_device; > u16 handle; > int num_luns; > u32 flags; > @@ -215,6 +227,7 @@ struct MPT2SAS_TARGET { > u8 tm_busy; > }; > > + > /* > * per device private data > */ > @@ -262,6 +275,12 @@ typedef struct _MPI2_CONFIG_PAGE_MAN_10 { > MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_10, > Mpi2ManufacturingPage10_t, MPI2_POINTER pMpi2ManufacturingPage10_t; > > +#define MFG_PAGE10_HIDE_SSDS_MASK (0x00000003) > +#define MFG_PAGE10_HIDE_ALL_DISKS (0x00) > +#define MFG_PAGE10_EXPOSE_ALL_DISKS (0x01) > +#define MFG_PAGE10_HIDE_IF_VOL_PRESENT (0x02) > + > + > struct MPT2SAS_DEVICE { > struct MPT2SAS_TARGET *sas_target; > unsigned int lun; > @@ -341,6 +360,7 @@ struct _sas_device { > * @sdev: scsi device struct (volumes are single lun) > * @wwid: unique identifier for the volume > * @handle: device handle > + * @block_size: Block size of the volume > * @id: target id > * @channel: target channel > * @volume_type: the raid level > @@ -348,20 +368,33 @@ struct _sas_device { > * @num_pds: number of hidden raid components > * @responding: used in _scsih_raid_device_mark_responding > * @percent_complete: resync percent complete > + * @direct_io_enabled: Whether direct io to PDs are allowed or not > + * @stripe_exponent: X where 2powX is the stripe sz in blocks > + * @max_lba: Maximum number of LBA in the volume > + * @stripe_sz: Stripe Size of the volume > + * @device_info: Device info of the volume member disk > + * @pd_handle: Array of handles of the physical drives for direct I/O > in le16 > */ > +#define MPT_MAX_WARPDRIVE_PDS 8 > struct _raid_device { > struct list_head list; > struct scsi_target *starget; > struct scsi_device *sdev; > u64 wwid; > u16 handle; > + u16 block_sz; > int id; > int channel; > u8 volume_type; > - u32 device_info; > u8 num_pds; > u8 responding; > u8 percent_complete; > + u8 direct_io_enabled; > + u8 stripe_exponent; > + u64 max_lba; > + u32 stripe_sz; > + u32 device_info; > + u16 pd_handle[MPT_MAX_WARPDRIVE_PDS]; > }; > > /** > @@ -470,6 +503,7 @@ struct chain_tracker { > * @smid: system message id > * @scmd: scsi request pointer > * @cb_idx: callback index > + * @direct_io: To indicate whether I/O is direct (WARPDRIVE) > * @chain_list: list of chains associated to this IO > * @tracker_list: list of free request (ioc->free_list) > */ > @@ -477,14 +511,14 @@ struct scsiio_tracker { > u16 smid; > struct scsi_cmnd *scmd; > u8 cb_idx; > + u8 direct_io; > struct list_head chain_list; > struct list_head tracker_list; > }; > > /** > - * struct request_tracker - misc mf request tracker > + * struct request_tracker - firmware request tracker > * @smid: system message id > - * @scmd: scsi request pointer > * @cb_idx: callback index > * @tracker_list: list of free request (ioc->free_list) > */ > @@ -832,6 +866,11 @@ struct MPT2SAS_ADAPTER { > u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT]; > u32 ring_buffer_offset; > u32 ring_buffer_sz; > + u8 is_warpdrive; > + u8 hide_ir_msg; > + u8 mfg_pg10_hide_flag; > + u8 hide_drives; > + > }; > > typedef u8 (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 > msix_index, > diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c > b/drivers/scsi/mpt2sas/mpt2sas_ctl.c > index e92b77a..e721457 100644 > --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c > +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c > @@ -1034,7 +1034,10 @@ _ctl_getiocinfo(void __user *arg) > __func__)); > > memset(&karg, 0 , sizeof(karg)); > - karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2; > + if (ioc->is_warpdrive) > + karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2_SSS6200; > + else > + karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2; > if (ioc->pfacts) > karg.port_number = ioc->pfacts[0].PortNumber; > pci_read_config_byte(ioc->pdev, PCI_CLASS_REVISION, &revision); > diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.h > b/drivers/scsi/mpt2sas/mpt2sas_ctl.h > index 69916e4..11ff1d5 100644 > --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.h > +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.h > @@ -133,6 +133,7 @@ struct mpt2_ioctl_pci_info { > #define MPT2_IOCTL_INTERFACE_FC_IP (0x02) > #define MPT2_IOCTL_INTERFACE_SAS (0x03) > #define MPT2_IOCTL_INTERFACE_SAS2 (0x04) > +#define MPT2_IOCTL_INTERFACE_SAS2_SSS6200 (0x05) > #define MPT2_IOCTL_VERSION_LENGTH (32) > > /** > diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c > b/drivers/scsi/mpt2sas/mpt2sas_scsih.c > index 6ceb775..87f6c31 100644 > --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c > +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c > @@ -233,6 +233,9 @@ static struct pci_device_id scsih_pci_table[] = { > PCI_ANY_ID, PCI_ANY_ID }, > { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3, > PCI_ANY_ID, PCI_ANY_ID }, > + /* SSS6200 */ > + { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200, > + PCI_ANY_ID, PCI_ANY_ID }, > {0} /* Terminating entry */ > }; > MODULE_DEVICE_TABLE(pci, scsih_pci_table); > @@ -1256,6 +1259,7 @@ _scsih_target_alloc(struct scsi_target *starget) > sas_target_priv_data->handle = raid_device->handle; > sas_target_priv_data->sas_address = raid_device- > >wwid; > sas_target_priv_data->flags |= > MPT_TARGET_FLAGS_VOLUME; > + sas_target_priv_data->raid_device = raid_device; > raid_device->starget = starget; > } > spin_unlock_irqrestore(&ioc->raid_device_lock, flags); > @@ -1455,7 +1459,10 @@ static int > _scsih_is_raid(struct device *dev) > { > struct scsi_device *sdev = to_scsi_device(dev); > + struct MPT2SAS_ADAPTER *ioc = shost_priv(sdev->host); > > + if (ioc->is_warpdrive) > + return 0; > return (sdev->channel == RAID_CHANNEL) ? 1 : 0; > } > > @@ -1480,7 +1487,7 @@ _scsih_get_resync(struct device *dev) > sdev->channel); > spin_unlock_irqrestore(&ioc->raid_device_lock, flags); > > - if (!raid_device) > + if (!raid_device || ioc->is_warpdrive) > goto out; > > if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0, > @@ -1640,6 +1647,212 @@ _scsih_get_volume_capabilities(struct > MPT2SAS_ADAPTER *ioc, > > kfree(vol_pg0); > } > +/** > + * _scsih_disable_ddio - Disable direct I/O for all the volumes > + * @ioc: per adapter object > + */ > +static void > +_scsih_disable_ddio(struct MPT2SAS_ADAPTER *ioc) > +{ > + Mpi2RaidVolPage1_t vol_pg1; > + Mpi2ConfigReply_t mpi_reply; > + struct _raid_device *raid_device; > + u16 handle; > + u16 ioc_status; > + > + handle = 0xFFFF; > + while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply, > + &vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, > handle))) { > + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & > + MPI2_IOCSTATUS_MASK; > + if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) > + break; > + handle = le16_to_cpu(vol_pg1.DevHandle); > + raid_device = _scsih_raid_device_find_by_handle(ioc, > handle); > + if (raid_device) > + raid_device->direct_io_enabled = 0; > + } > + return; > +} > + > + > +/** > + * _scsih_get_num_volumes - Get number of volumes in the ioc > + * @ioc: per adapter object > + */ > +static u8 > +_scsih_get_num_volumes(struct MPT2SAS_ADAPTER *ioc) > +{ > + Mpi2RaidVolPage1_t vol_pg1; > + Mpi2ConfigReply_t mpi_reply; > + u16 handle; > + u8 vol_cnt = 0; > + u16 ioc_status; > + > + handle = 0xFFFF; > + while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply, > + &vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, > handle))) { > + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & > + MPI2_IOCSTATUS_MASK; > + if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) > + break; > + vol_cnt++; > + handle = le16_to_cpu(vol_pg1.DevHandle); > + } > + return vol_cnt; > +} > + > + > +/** > + * _scsih_init_warpdrive_properties - Set properties for warpdrive > direct I/O. > + * @ioc: per adapter object > + * @raid_device: the raid_device object > + */ > +static void > +_scsih_init_warpdrive_properties(struct MPT2SAS_ADAPTER *ioc, > + struct _raid_device *raid_device) > +{ > + Mpi2RaidVolPage0_t *vol_pg0; > + Mpi2RaidPhysDiskPage0_t pd_pg0; > + Mpi2ConfigReply_t mpi_reply; > + u16 sz; > + u8 num_pds, count; > + u64 mb = 1024 * 1024; > + u64 tb_2 = 2 * mb * mb; > + u64 capacity; > + u32 stripe_sz; > + u8 i, stripe_exp; > + > + if (!ioc->is_warpdrive) > + return; > + > + if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS) { > + printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled > " > + "globally as drives are exposed\n", ioc->name); > + return; > + } > + if (_scsih_get_num_volumes(ioc) > 1) { > + _scsih_disable_ddio(ioc); > + printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled > " > + "globally as number of drives > 1\n", ioc->name); > + return; > + } > + if ((mpt2sas_config_get_number_pds(ioc, raid_device->handle, > + &num_pds)) || !num_pds) { > + printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled > " > + "Failure in computing number of drives\n", ioc->name); > + return; > + } > + > + sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds * > + sizeof(Mpi2RaidVol0PhysDisk_t)); > + vol_pg0 = kzalloc(sz, GFP_KERNEL); > + if (!vol_pg0) { > + printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled > " > + "Memory allocation failure for RVPG0\n", ioc->name); > + return; > + } > + > + if ((mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0, > + MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, > sz))) { > + printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled > " > + "Failure in retrieving RVPG0\n", ioc->name); > + kfree(vol_pg0); > + return; > + } > + > + /* > + * WARPDRIVE:If number of physical disks in a volume exceeds the > max pds > + * assumed for WARPDRIVE, disable direct I/O > + */ > + if (num_pds > MPT_MAX_WARPDRIVE_PDS) { > + printk(MPT2SAS_WARN_FMT "WarpDrive : Direct IO is disabled > " > + "for the drive with handle(0x%04x): num_mem=%d, " > + "max_mem_allowed=%d\n", ioc->name, raid_device->handle, > + num_pds, MPT_MAX_WARPDRIVE_PDS); > + kfree(vol_pg0); > + return; > + } > + for (count = 0; count < num_pds; count++) { > + if (mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply, > + &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM, > + vol_pg0->PhysDisk[count].PhysDiskNum) || > + pd_pg0.DevHandle == MPT2SAS_INVALID_DEVICE_HANDLE) { > + printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is " > + "disabled for the drive with handle(0x%04x) > member" > + "handle retrieval failed for member number=%d\n", > + ioc->name, raid_device->handle, > + vol_pg0->PhysDisk[count].PhysDiskNum); > + goto out_error; > + } > + raid_device->pd_handle[count] = > le16_to_cpu(pd_pg0.DevHandle); > + } > + > + /* > + * Assumption for WD: Direct I/O is not supported if the volume > is > + * not RAID0, if the stripe size is not 64KB, if the block size > is > + * not 512 and if the volume size is >2TB > + */ > + if (raid_device->volume_type != MPI2_RAID_VOL_TYPE_RAID0 || > + le16_to_cpu(vol_pg0->BlockSize) != 512) { > + printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled > " > + "for the drive with handle(0x%04x): type=%d, " > + "s_sz=%uK, blk_size=%u\n", ioc->name, > + raid_device->handle, raid_device->volume_type, > + le32_to_cpu(vol_pg0->StripeSize)/2, > + le16_to_cpu(vol_pg0->BlockSize)); > + goto out_error; > + } > + > + capacity = (u64) le16_to_cpu(vol_pg0->BlockSize) * > + (le64_to_cpu(vol_pg0->MaxLBA) + 1); > + > + if (capacity > tb_2) { > + printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled > " > + "for the drive with handle(0x%04x) since drive sz > 2TB\n", > + ioc->name, raid_device->handle); > + goto out_error; > + } > + > + stripe_sz = le32_to_cpu(vol_pg0->StripeSize); > + stripe_exp = 0; > + for (i = 0; i < 32; i++) { > + if (stripe_sz & 1) > + break; > + stripe_exp++; > + stripe_sz >>= 1; > + } > + if (i == 32) { > + printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled > " > + "for the drive with handle(0x%04x) invalid stripe sz > %uK\n", > + ioc->name, raid_device->handle, > + le32_to_cpu(vol_pg0->StripeSize)/2); > + goto out_error; > + } > + raid_device->stripe_exponent = stripe_exp; > + raid_device->direct_io_enabled = 1; > + > + printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is Enabled for the > drive" > + " with handle(0x%04x)\n", ioc->name, raid_device->handle); > + /* > + * WARPDRIVE: Though the following fields are not used for direct > IO, > + * stored for future purpose: > + */ > + raid_device->max_lba = le64_to_cpu(vol_pg0->MaxLBA); > + raid_device->stripe_sz = le32_to_cpu(vol_pg0->StripeSize); > + raid_device->block_sz = le16_to_cpu(vol_pg0->BlockSize); > + > + > + kfree(vol_pg0); > + return; > + > +out_error: > + raid_device->direct_io_enabled = 0; > + for (count = 0; count < num_pds; count++) > + raid_device->pd_handle[count] = 0; > + kfree(vol_pg0); > + return; > +} > > /** > * _scsih_enable_tlr - setting TLR flags > @@ -1710,6 +1923,11 @@ _scsih_slave_configure(struct scsi_device *sdev) > > _scsih_get_volume_capabilities(ioc, raid_device); > > + /* > + * WARPDRIVE: Initialize the required data for Direct IO > + */ > + _scsih_init_warpdrive_properties(ioc, raid_device); > + > /* RAID Queue Depth Support > * IS volume = underlying qdepth of drive type, either > * MPT2SAS_SAS_QUEUE_DEPTH or MPT2SAS_SATA_QUEUE_DEPTH > @@ -1757,14 +1975,16 @@ _scsih_slave_configure(struct scsi_device > *sdev) > break; > } > > - sdev_printk(KERN_INFO, sdev, "%s: " > - "handle(0x%04x), wwid(0x%016llx), pd_count(%d), > type(%s)\n", > - r_level, raid_device->handle, > - (unsigned long long)raid_device->wwid, > - raid_device->num_pds, ds); > + if (!ioc->hide_ir_msg) > + sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), " > + "wwid(0x%016llx), pd_count(%d), type(%s)\n", > + r_level, raid_device->handle, > + (unsigned long long)raid_device->wwid, > + raid_device->num_pds, ds); > _scsih_change_queue_depth(sdev, qdepth, > SCSI_QDEPTH_DEFAULT); > /* raid transport support */ > - _scsih_set_level(sdev, raid_device); > + if (!ioc->is_warpdrive) > + _scsih_set_level(sdev, raid_device); > return 0; > } > > @@ -2182,16 +2402,20 @@ _scsih_tm_display_info(struct MPT2SAS_ADAPTER > *ioc, struct scsi_cmnd *scmd) > struct MPT2SAS_TARGET *priv_target = starget->hostdata; > struct _sas_device *sas_device = NULL; > unsigned long flags; > + char *device_str = NULL; > > if (!priv_target) > return; > + if (ioc->hide_ir_msg) > + device_str = "WarpDrive"; > + else > + device_str = "volume"; > > scsi_print_command(scmd); > if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) { > - starget_printk(KERN_INFO, starget, "volume handle(0x%04x), > " > - "volume wwid(0x%016llx)\n", > - priv_target->handle, > - (unsigned long long)priv_target->sas_address); > + starget_printk(KERN_INFO, starget, "%s handle(0x%04x), " > + "%s wwid(0x%016llx)\n", device_str, priv_target- > >handle, > + device_str, (unsigned long long)priv_target- > >sas_address); > } else { > spin_lock_irqsave(&ioc->sas_device_lock, flags); > sas_device = > mpt2sas_scsih_sas_device_find_by_sas_address(ioc, > @@ -3130,6 +3354,9 @@ _scsih_check_ir_config_unhide_events(struct > MPT2SAS_ADAPTER *ioc, > a = 0; > b = 0; > > + if (ioc->is_warpdrive) > + return; > + > /* Volume Resets for Deleted or Removed */ > element = (Mpi2EventIrConfigElement_t *)&event_data- > >ConfigElement[0]; > for (i = 0; i < event_data->NumElements; i++, element++) { > @@ -3347,6 +3574,105 @@ _scsih_eedp_error_handling(struct scsi_cmnd > *scmd, u16 ioc_status) > } > > /** > + * _scsih_scsi_direct_io_get - returns direct io flag > + * @ioc: per adapter object > + * @smid: system request message index > + * > + * Returns the smid stored scmd pointer. > + */ > +static inline u8 > +_scsih_scsi_direct_io_get(struct MPT2SAS_ADAPTER *ioc, u16 smid) > +{ > + return ioc->scsi_lookup[smid - 1].direct_io; > +} > + > +/** > + * _scsih_scsi_direct_io_set - sets direct io flag > + * @ioc: per adapter object > + * @smid: system request message index > + * @direct_io: Zero or non-zero value to set in the direct_io flag > + * > + * Returns Nothing. > + */ > +static inline void > +_scsih_scsi_direct_io_set(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 > direct_io) > +{ > + ioc->scsi_lookup[smid - 1].direct_io = direct_io; > +} > + > + > +/** > + * _scsih_setup_direct_io - setup MPI request for WARPDRIVE Direct I/O > + * @ioc: per adapter object > + * @scmd: pointer to scsi command object > + * @raid_device: pointer to raid device data structure > + * @mpi_request: pointer to the SCSI_IO reqest message frame > + * @smid: system request message index > + * > + * Returns nothing > + */ > +static void > +_scsih_setup_direct_io(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd > *scmd, > + struct _raid_device *raid_device, Mpi2SCSIIORequest_t > *mpi_request, > + u16 smid) > +{ > + u32 v_lba, p_lba, stripe_off, stripe_unit, column, io_size; > + u32 stripe_sz, stripe_exp; > + u8 num_pds, *cdb_ptr, *tmp_ptr, *lba_ptr1, *lba_ptr2; > + u8 cdb0 = scmd->cmnd[0]; > + > + /* > + * Try Direct I/O to RAID memeber disks > + */ > + if (cdb0 == READ_16 || cdb0 == READ_10 || > + cdb0 == WRITE_16 || cdb0 == WRITE_10) { > + cdb_ptr = mpi_request->CDB.CDB32; > + > + if ((cdb0 < READ_16) || !(cdb_ptr[2] | cdb_ptr[3] | > cdb_ptr[4] > + | cdb_ptr[5])) { > + io_size = scsi_bufflen(scmd) >> 9; > + /* get virtual lba */ > + lba_ptr1 = lba_ptr2 = (cdb0 < READ_16) ? &cdb_ptr[2] > : > + &cdb_ptr[6]; > + tmp_ptr = (u8 *)&v_lba + 3; > + *tmp_ptr-- = *lba_ptr1++; > + *tmp_ptr-- = *lba_ptr1++; > + *tmp_ptr-- = *lba_ptr1++; > + *tmp_ptr = *lba_ptr1; > + > + if (((u64)v_lba + (u64)io_size - 1) <= > + (u32)raid_device->max_lba) { > + stripe_sz = raid_device->stripe_sz; > + stripe_exp = raid_device->stripe_exponent; > + stripe_off = v_lba & (stripe_sz - 1); > + > + /* Check whether IO falls within a stripe */ > + if ((stripe_off + io_size) <= stripe_sz) { > + num_pds = raid_device->num_pds; > + p_lba = v_lba >> stripe_exp; > + stripe_unit = p_lba / num_pds; > + column = p_lba % num_pds; > + p_lba = (stripe_unit << stripe_exp) + > + stripe_off; > + mpi_request->DevHandle = > + cpu_to_le16(raid_device-> > + pd_handle[column]); > + tmp_ptr = (u8 *)&p_lba + 3; > + *lba_ptr2++ = *tmp_ptr--; > + *lba_ptr2++ = *tmp_ptr--; > + *lba_ptr2++ = *tmp_ptr--; > + *lba_ptr2 = *tmp_ptr; > + /* > + * WD: To indicate this I/O is directI/O > + */ > + _scsih_scsi_direct_io_set(ioc, smid, 1); > + } > + } > + } > + } > +} > + > +/** > * _scsih_qcmd - main scsi request entry point > * @scmd: pointer to scsi command object > * @done: function pointer to be invoked on completion > @@ -3363,6 +3689,7 @@ _scsih_qcmd_lck(struct scsi_cmnd *scmd, void > (*done)(struct scsi_cmnd *)) > struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host); > struct MPT2SAS_DEVICE *sas_device_priv_data; > struct MPT2SAS_TARGET *sas_target_priv_data; > + struct _raid_device *raid_device; > Mpi2SCSIIORequest_t *mpi_request; > u32 mpi_control; > u16 smid; > @@ -3424,8 +3751,10 @@ _scsih_qcmd_lck(struct scsi_cmnd *scmd, void > (*done)(struct scsi_cmnd *)) > > } else > mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ; > - /* Make sure Device is not raid volume */ > - if (!_scsih_is_raid(&scmd->device->sdev_gendev) && > + /* Make sure Device is not raid volume. > + * We do not expose raid functionality to upper layer for > warpdrive. > + */ > + if (!ioc->is_warpdrive && !_scsih_is_raid(&scmd->device- > >sdev_gendev) && > sas_is_tlr_enabled(scmd->device) && scmd->cmd_len != 32) > mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON; > > @@ -3473,9 +3802,14 @@ _scsih_qcmd_lck(struct scsi_cmnd *scmd, void > (*done)(struct scsi_cmnd *)) > } > } > > + raid_device = sas_target_priv_data->raid_device; > + if (raid_device && raid_device->direct_io_enabled) > + _scsih_setup_direct_io(ioc, scmd, raid_device, mpi_request, > + smid); > + > if (likely(mpi_request->Function == > MPI2_FUNCTION_SCSI_IO_REQUEST)) > mpt2sas_base_put_smid_scsi_io(ioc, smid, > - sas_device_priv_data->sas_target->handle); > + le16_to_cpu(mpi_request->DevHandle)); > else > mpt2sas_base_put_smid_default(ioc, smid); > return 0; > @@ -3540,10 +3874,16 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER > *ioc, struct scsi_cmnd *scmd, > unsigned long flags; > struct scsi_target *starget = scmd->device->sdev_target; > struct MPT2SAS_TARGET *priv_target = starget->hostdata; > + char *device_str = NULL; > > if (!priv_target) > return; > > + if (ioc->hide_ir_msg) > + device_str = "WarpDrive"; > + else > + device_str = "volume"; > + > if (log_info == 0x31170000) > return; > > @@ -3660,8 +4000,8 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, > struct scsi_cmnd *scmd, > scsi_print_command(scmd); > > if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) { > - printk(MPT2SAS_WARN_FMT "\tvolume wwid(0x%016llx)\n", ioc- > >name, > - (unsigned long long)priv_target->sas_address); > + printk(MPT2SAS_WARN_FMT "\t%s wwid(0x%016llx)\n", ioc- > >name, > + device_str, (unsigned long long)priv_target- > >sas_address); > } else { > spin_lock_irqsave(&ioc->sas_device_lock, flags); > sas_device = > mpt2sas_scsih_sas_device_find_by_sas_address(ioc, > @@ -3840,6 +4180,20 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 > smid, u8 msix_index, u32 reply) > scmd->result = DID_NO_CONNECT << 16; > goto out; > } > + /* > + * WARPDRIVE: If direct_io is set then it is directIO, > + * the failed direct I/O should be redirected to volume > + */ > + if (_scsih_scsi_direct_io_get(ioc, smid)) { > + _scsih_scsi_direct_io_set(ioc, smid, 0); > + memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len); > + mpi_request->DevHandle = > + cpu_to_le16(sas_device_priv_data->sas_target->handle); > + mpt2sas_base_put_smid_scsi_io(ioc, smid, > + sas_device_priv_data->sas_target->handle); > + return 0; > + } > + > > /* turning off TLR */ > scsi_state = mpi_reply->SCSIState; > @@ -3848,7 +4202,10 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 > smid, u8 msix_index, u32 reply) > le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF; > if (!sas_device_priv_data->tlr_snoop_check) { > sas_device_priv_data->tlr_snoop_check++; > - if (!_scsih_is_raid(&scmd->device->sdev_gendev) && > + /* Make sure Device is not raid volume. > + * We do not expose raid functionality to upper layer for > warpdrive. > + */ > + if (!ioc->is_warpdrive && !_scsih_is_raid(&scmd->device- > >sdev_gendev) && > sas_is_tlr_enabled(scmd->device) && > response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) { > sas_disable_tlr(scmd->device); > @@ -4681,8 +5038,10 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER > *ioc, > > _scsih_ublock_io_device(ioc, sas_device_backup.handle); > > - mpt2sas_transport_port_remove(ioc, sas_device_backup.sas_address, > - sas_device_backup.sas_address_parent); > + if (!ioc->hide_drives) > + mpt2sas_transport_port_remove(ioc, > + sas_device_backup.sas_address, > + sas_device_backup.sas_address_parent); > > printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), sas_addr" > "(0x%016llx)\n", ioc->name, sas_device_backup.handle, > @@ -5413,6 +5772,7 @@ _scsih_sas_pd_hide(struct MPT2SAS_ADAPTER *ioc, > &sas_device->volume_wwid); > set_bit(handle, ioc->pd_handles); > _scsih_reprobe_target(sas_device->starget, 1); > + > } > > /** > @@ -5591,7 +5951,8 @@ _scsih_sas_ir_config_change_event(struct > MPT2SAS_ADAPTER *ioc, > Mpi2EventDataIrConfigChangeList_t *event_data = fw_event- > >event_data; > > #ifdef CONFIG_SCSI_MPT2SAS_LOGGING > - if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) > + if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) > + && !ioc->hide_ir_msg) > _scsih_sas_ir_config_change_event_debug(ioc, event_data); > > #endif > @@ -5614,16 +5975,20 @@ _scsih_sas_ir_config_change_event(struct > MPT2SAS_ADAPTER *ioc, > le16_to_cpu(element->VolDevHandle)); > break; > case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: > - _scsih_sas_pd_hide(ioc, element); > + if (!ioc->is_warpdrive) > + _scsih_sas_pd_hide(ioc, element); > break; > case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED: > - _scsih_sas_pd_expose(ioc, element); > + if (!ioc->is_warpdrive) > + _scsih_sas_pd_expose(ioc, element); > break; > case MPI2_EVENT_IR_CHANGE_RC_HIDE: > - _scsih_sas_pd_add(ioc, element); > + if (!ioc->is_warpdrive) > + _scsih_sas_pd_add(ioc, element); > break; > case MPI2_EVENT_IR_CHANGE_RC_UNHIDE: > - _scsih_sas_pd_delete(ioc, element); > + if (!ioc->is_warpdrive) > + _scsih_sas_pd_delete(ioc, element); > break; > } > } > @@ -5654,9 +6019,10 @@ _scsih_sas_ir_volume_event(struct > MPT2SAS_ADAPTER *ioc, > > handle = le16_to_cpu(event_data->VolDevHandle); > state = le32_to_cpu(event_data->NewValue); > - dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle(0x%04x), " > - "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle, > - le32_to_cpu(event_data->PreviousValue), state)); > + if (!ioc->hide_ir_msg) > + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: > handle(0x%04x), " > + "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, > handle, > + le32_to_cpu(event_data->PreviousValue), state)); > > switch (state) { > case MPI2_RAID_VOL_STATE_MISSING: > @@ -5736,9 +6102,10 @@ _scsih_sas_ir_physical_disk_event(struct > MPT2SAS_ADAPTER *ioc, > handle = le16_to_cpu(event_data->PhysDiskDevHandle); > state = le32_to_cpu(event_data->NewValue); > > - dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle(0x%04x), " > - "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle, > - le32_to_cpu(event_data->PreviousValue), state)); > + if (!ioc->hide_ir_msg) > + dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: > handle(0x%04x), " > + "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, > handle, > + le32_to_cpu(event_data->PreviousValue), state)); > > switch (state) { > case MPI2_RAID_PD_STATE_ONLINE: > @@ -5747,7 +6114,8 @@ _scsih_sas_ir_physical_disk_event(struct > MPT2SAS_ADAPTER *ioc, > case MPI2_RAID_PD_STATE_OPTIMAL: > case MPI2_RAID_PD_STATE_HOT_SPARE: > > - set_bit(handle, ioc->pd_handles); > + if (!ioc->is_warpdrive) > + set_bit(handle, ioc->pd_handles); > > spin_lock_irqsave(&ioc->sas_device_lock, flags); > sas_device = _scsih_sas_device_find_by_handle(ioc, handle); > @@ -5851,7 +6219,8 @@ _scsih_sas_ir_operation_status_event(struct > MPT2SAS_ADAPTER *ioc, > u16 handle; > > #ifdef CONFIG_SCSI_MPT2SAS_LOGGING > - if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) > + if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) > + && !ioc->hide_ir_msg) > _scsih_sas_ir_operation_status_event_debug(ioc, > event_data); > #endif > @@ -5910,7 +6279,7 @@ static void > _scsih_mark_responding_sas_device(struct MPT2SAS_ADAPTER *ioc, u64 > sas_address, > u16 slot, u16 handle) > { > - struct MPT2SAS_TARGET *sas_target_priv_data; > + struct MPT2SAS_TARGET *sas_target_priv_data = NULL; > struct scsi_target *starget; > struct _sas_device *sas_device; > unsigned long flags; > @@ -5918,7 +6287,7 @@ _scsih_mark_responding_sas_device(struct > MPT2SAS_ADAPTER *ioc, u64 sas_address, > spin_lock_irqsave(&ioc->sas_device_lock, flags); > list_for_each_entry(sas_device, &ioc->sas_device_list, list) { > if (sas_device->sas_address == sas_address && > - sas_device->slot == slot && sas_device->starget) { > + sas_device->slot == slot) { > sas_device->responding = 1; > starget = sas_device->starget; > if (starget && starget->hostdata) { > @@ -5927,13 +6296,15 @@ _scsih_mark_responding_sas_device(struct > MPT2SAS_ADAPTER *ioc, u64 sas_address, > sas_target_priv_data->deleted = 0; > } else > sas_target_priv_data = NULL; > - starget_printk(KERN_INFO, sas_device->starget, > - "handle(0x%04x), sas_addr(0x%016llx), enclosure " > - "logical id(0x%016llx), slot(%d)\n", handle, > - (unsigned long long)sas_device->sas_address, > - (unsigned long long) > - sas_device->enclosure_logical_id, > - sas_device->slot); > + if (starget) > + starget_printk(KERN_INFO, starget, > + "handle(0x%04x), sas_addr(0x%016llx), " > + "enclosure logical id(0x%016llx), " > + "slot(%d)\n", handle, > + (unsigned long long)sas_device- > >sas_address, > + (unsigned long long) > + sas_device->enclosure_logical_id, > + sas_device->slot); > if (sas_device->handle == handle) > goto out; > printk(KERN_INFO "\thandle changed > from(0x%04x)!!!\n", > @@ -6025,6 +6396,12 @@ _scsih_mark_responding_raid_device(struct > MPT2SAS_ADAPTER *ioc, u64 wwid, > starget_printk(KERN_INFO, raid_device->starget, > "handle(0x%04x), wwid(0x%016llx)\n", handle, > (unsigned long long)raid_device->wwid); > + /* > + * WARPDRIVE: The handles of the PDs might have > changed > + * across the host reset so re-initialize the > + * required data for Direct IO > + */ > + _scsih_init_warpdrive_properties(ioc, raid_device); > if (raid_device->handle == handle) > goto out; > printk(KERN_INFO "\thandle changed > from(0x%04x)!!!\n", > @@ -6086,18 +6463,20 @@ _scsih_search_responding_raid_devices(struct > MPT2SAS_ADAPTER *ioc) > } > > /* refresh the pd_handles */ > - phys_disk_num = 0xFF; > - memset(ioc->pd_handles, 0, ioc->pd_handles_sz); > - while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply, > - &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM, > - phys_disk_num))) { > - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & > - MPI2_IOCSTATUS_MASK; > - if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) > - break; > - phys_disk_num = pd_pg0.PhysDiskNum; > - handle = le16_to_cpu(pd_pg0.DevHandle); > - set_bit(handle, ioc->pd_handles); > + if (!ioc->is_warpdrive) { > + phys_disk_num = 0xFF; > + memset(ioc->pd_handles, 0, ioc->pd_handles_sz); > + while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply, > + &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM, > + phys_disk_num))) { > + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & > + MPI2_IOCSTATUS_MASK; > + if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) > + break; > + phys_disk_num = pd_pg0.PhysDiskNum; > + handle = le16_to_cpu(pd_pg0.DevHandle); > + set_bit(handle, ioc->pd_handles); > + } > } > } > > @@ -6243,6 +6622,50 @@ _scsih_remove_unresponding_sas_devices(struct > MPT2SAS_ADAPTER *ioc) > } > > /** > + * _scsih_hide_unhide_sas_devices - add/remove device to/from OS > + * @ioc: per adapter object > + * > + * Return nothing. > + */ > +static void > +_scsih_hide_unhide_sas_devices(struct MPT2SAS_ADAPTER *ioc) > +{ > + struct _sas_device *sas_device, *sas_device_next; > + > + if (!ioc->is_warpdrive || ioc->mfg_pg10_hide_flag != > + MFG_PAGE10_HIDE_IF_VOL_PRESENT) > + return; > + > + if (ioc->hide_drives) { > + if (_scsih_get_num_volumes(ioc)) > + return; > + ioc->hide_drives = 0; > + list_for_each_entry_safe(sas_device, sas_device_next, > + &ioc->sas_device_list, list) { > + if (!mpt2sas_transport_port_add(ioc, sas_device- > >handle, > + sas_device->sas_address_parent)) { > + _scsih_sas_device_remove(ioc, sas_device); > + } else if (!sas_device->starget) { > + mpt2sas_transport_port_remove(ioc, > + sas_device->sas_address, > + sas_device->sas_address_parent); > + _scsih_sas_device_remove(ioc, sas_device); > + } > + } > + } else { > + if (!_scsih_get_num_volumes(ioc)) > + return; > + ioc->hide_drives = 1; > + list_for_each_entry_safe(sas_device, sas_device_next, > + &ioc->sas_device_list, list) { > + mpt2sas_transport_port_remove(ioc, > + sas_device->sas_address, > + sas_device->sas_address_parent); > + } > + } > +} > + > +/** > * mpt2sas_scsih_reset_handler - reset callback handler (for scsih) > * @ioc: per adapter object > * @reset_phase: phase > @@ -6326,6 +6749,7 @@ _firmware_event_work(struct work_struct *work) > spin_unlock_irqrestore(&ioc- > >ioc_reset_in_progress_lock, > flags); > _scsih_remove_unresponding_sas_devices(ioc); > + _scsih_hide_unhide_sas_devices(ioc); > return; > } > > @@ -6425,6 +6849,53 @@ mpt2sas_scsih_event_callback(struct > MPT2SAS_ADAPTER *ioc, u8 msix_index, > (Mpi2EventDataIrVolume_t *) > mpi_reply->EventData); > break; > + case MPI2_EVENT_LOG_ENTRY_ADDED: > + { > + Mpi2EventDataLogEntryAdded_t *log_entry; > + u32 *log_code; > + > + if (!ioc->is_warpdrive) > + break; > + > + log_entry = (Mpi2EventDataLogEntryAdded_t *) > + mpi_reply->EventData; > + log_code = (u32 *)log_entry->LogData; > + > + if (le16_to_cpu(log_entry->LogEntryQualifier) > + != MPT2_WARPDRIVE_LOGENTRY) > + break; > + > + switch (le32_to_cpu(*log_code)) { > + case MPT2_WARPDRIVE_LC_SSDT: > + printk(MPT2SAS_WARN_FMT "WarpDrive Warning: " > + "IO Throttling has occurred in the WarpDrive " > + "subsystem. Check WarpDrive documentation for " > + "additional details.\n", ioc->name); > + break; > + case MPT2_WARPDRIVE_LC_SSDLW: > + printk(MPT2SAS_WARN_FMT "WarpDrive Warning: " > + "Program/Erase Cycles for the WarpDrive subsystem > " > + "in degraded range. Check WarpDrive documentation > " > + "for additional details.\n", ioc->name); > + break; > + case MPT2_WARPDRIVE_LC_SSDLF: > + printk(MPT2SAS_ERR_FMT "WarpDrive Fatal Error: " > + "There are no Program/Erase Cycles for the " > + "WarpDrive subsystem. The storage device will be > " > + "in read-only mode. Check WarpDrive documentation > " > + "for additional details.\n", ioc->name); > + break; > + case MPT2_WARPDRIVE_LC_BRMF: > + printk(MPT2SAS_ERR_FMT "WarpDrive Fatal Error: " > + "The Backup Rail Monitor has failed on the " > + "WarpDrive subsystem. Check WarpDrive " > + "documentation for additional details.\n", > + ioc->name); > + break; > + } > + > + break; > + } > case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: > case MPI2_EVENT_IR_OPERATION_STATUS: > case MPI2_EVENT_SAS_DISCOVERY: > @@ -6583,7 +7054,8 @@ _scsih_ir_shutdown(struct MPT2SAS_ADAPTER *ioc) > mpi_request->Function = MPI2_FUNCTION_RAID_ACTION; > mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED; > > - printk(MPT2SAS_INFO_FMT "IR shutdown (sending)\n", ioc->name); > + if (!ioc->hide_ir_msg) > + printk(MPT2SAS_INFO_FMT "IR shutdown (sending)\n", ioc- > >name); > init_completion(&ioc->scsih_cmds.done); > mpt2sas_base_put_smid_default(ioc, smid); > wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ); > @@ -6597,10 +7069,11 @@ _scsih_ir_shutdown(struct MPT2SAS_ADAPTER *ioc) > if (ioc->scsih_cmds.status & MPT2_CMD_REPLY_VALID) { > mpi_reply = ioc->scsih_cmds.reply; > > - printk(MPT2SAS_INFO_FMT "IR shutdown (complete): " > - "ioc_status(0x%04x), loginfo(0x%08x)\n", > - ioc->name, le16_to_cpu(mpi_reply->IOCStatus), > - le32_to_cpu(mpi_reply->IOCLogInfo)); > + if (!ioc->hide_ir_msg) > + printk(MPT2SAS_INFO_FMT "IR shutdown (complete): " > + "ioc_status(0x%04x), loginfo(0x%08x)\n", > + ioc->name, le16_to_cpu(mpi_reply->IOCStatus), > + le32_to_cpu(mpi_reply->IOCLogInfo)); > } > > out: > @@ -6759,6 +7232,9 @@ _scsih_probe_boot_devices(struct MPT2SAS_ADAPTER > *ioc) > spin_lock_irqsave(&ioc->sas_device_lock, flags); > list_move_tail(&sas_device->list, &ioc->sas_device_list); > spin_unlock_irqrestore(&ioc->sas_device_lock, flags); > + > + if (ioc->hide_drives) > + return; > if (!mpt2sas_transport_port_add(ioc, sas_device->handle, > sas_device->sas_address_parent)) { > _scsih_sas_device_remove(ioc, sas_device); > @@ -6812,6 +7288,9 @@ _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc) > list_move_tail(&sas_device->list, &ioc->sas_device_list); > spin_unlock_irqrestore(&ioc->sas_device_lock, flags); > > + if (ioc->hide_drives) > + continue; > + > if (!mpt2sas_transport_port_add(ioc, sas_device->handle, > sas_device->sas_address_parent)) { > _scsih_sas_device_remove(ioc, sas_device); > @@ -6882,6 +7361,11 @@ _scsih_probe(struct pci_dev *pdev, const struct > pci_device_id *id) > ioc->id = mpt_ids++; > sprintf(ioc->name, "%s%d", MPT2SAS_DRIVER_NAME, ioc->id); > ioc->pdev = pdev; > + if (id->device == MPI2_MFGPAGE_DEVID_SSS6200) { > + ioc->is_warpdrive = 1; > + ioc->hide_ir_msg = 1; > + } else > + ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS; > ioc->scsi_io_cb_idx = scsi_io_cb_idx; > ioc->tm_cb_idx = tm_cb_idx; > ioc->ctl_cb_idx = ctl_cb_idx; > @@ -6947,6 +7431,20 @@ _scsih_probe(struct pci_dev *pdev, const struct > pci_device_id *id) > } > > ioc->wait_for_port_enable_to_complete = 0; > + if (ioc->is_warpdrive) { > + if (ioc->mfg_pg10_hide_flag == > MFG_PAGE10_EXPOSE_ALL_DISKS) > + ioc->hide_drives = 0; > + else if (ioc->mfg_pg10_hide_flag == > MFG_PAGE10_HIDE_ALL_DISKS) > + ioc->hide_drives = 1; > + else { > + if (_scsih_get_num_volumes(ioc)) > + ioc->hide_drives = 1; > + else > + ioc->hide_drives = 0; > + } > + } else > + ioc->hide_drives = 0; > + > _scsih_probe_devices(ioc); > return 0; > > -- > To unsubscribe from this list: send the line "unsubscribe linux-scsi" > in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html