RE: [PATCH] [Resend with git format] mpt2sas : WarpDrive New product SSS6200 support added

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux