Re: [PATCH] MVSAS: hot plug handling and IO issues

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

 



Hello Srinivas,

I've recompiled kernel 2.6.32.7 on a CentOS 5.5 box using the .config
from /boot/config-2.6.18-164.2.1.el5

- added your patch
- using mdelay (100).

Regarding the previous errors reported: I made the mistake of taking a
working 2.6.32.7 .config which was running fine with your patch on
another Fedora 13 box for some time, and re-using that .config on a
CentOS 5.5 box. Big mistake. The slow deletion is now gone, it seemed
the non mvsas attached disks were also affected.

Now for the first time, I get "Unplug Notice" from mv_sas:

drivers/scsi/mvsas/mv_sas.c 1700:<7>mv_abort_task()
mvi=ffff88003ee80000 task=ffff88003b66b840 slot=ffff88003ee9c3e0
slot_idx=x0
drivers/scsi/mvsas/mv_sas.c 1631:mvs_query_task:rc= 5
drivers/scsi/mvsas/mv_sas.c 2081:port 3 ctrl sts=0x89800.
drivers/scsi/mvsas/mv_sas.c 2083:Port 3 irq sts = 0x1001
drivers/scsi/mvsas/mv_sas.c 2109:phy3 Unplug Notice
drivers/scsi/mvsas/mv_sas.c 2081:port 3 ctrl sts=0x199800.
drivers/scsi/mvsas/mv_sas.c 2083:Port 3 irq sts = 0x1081
drivers/scsi/mvsas/mv_sas.c 2081:port 3 ctrl sts=0x199800.
drivers/scsi/mvsas/mv_sas.c 2083:Port 3 irq sts = 0x10000
drivers/scsi/mvsas/mv_sas.c 2136:notify plug in on phy[3]
drivers/scsi/mvsas/mv_sas.c 1223:port 3 attach dev info is 2000000
drivers/scsi/mvsas/mv_sas.c 1225:port 3 attach sas addr is 3
drivers/scsi/mvsas/mv_sas.c 378:phy 3 byte dmaded.
drivers/scsi/mvsas/mv_sas.c 1585:mvs_I_T_nexus_reset for device[3]:rc= 0
ata12: translated ATA stat/err 0x01/04 to SCSI SK/ASC/ASCQ 0xb/00/00
ata12: status=0x01 { Error }
ata12: error=0x04 { DriveStatusError }

I'm pretty sure these disks are never unplugged as they are hard-wired
in the case and not part of a hotplug backplane.

I've reverted to mdelay (10), but the Unplug notice still occurs, e.g.
when doing a large copy:

drivers/scsi/mvsas/mv_sas.c 1700:<7>mv_abort_task()
mvi=ffff88003c880000 task=ffff880015483e40 slot=ffff88003c89c438
slot_idx=x1
drivers/scsi/mvsas/mv_sas.c 1631:mvs_query_task:rc= 5
drivers/scsi/mvsas/mv_sas.c 2081:port 3 ctrl sts=0x89800.
drivers/scsi/mvsas/mv_sas.c 2083:Port 3 irq sts = 0x1001
drivers/scsi/mvsas/mv_sas.c 2109:phy3 Unplug Notice
drivers/scsi/mvsas/mv_sas.c 2081:port 3 ctrl sts=0x199800.
drivers/scsi/mvsas/mv_sas.c 2083:Port 3 irq sts = 0x1081
drivers/scsi/mvsas/mv_sas.c 2081:port 3 ctrl sts=0x199800.
drivers/scsi/mvsas/mv_sas.c 2083:Port 3 irq sts = 0x10000
drivers/scsi/mvsas/mv_sas.c 2136:notify plug in on phy[3]
drivers/scsi/mvsas/mv_sas.c 1223:port 3 attach dev info is 2000000
drivers/scsi/mvsas/mv_sas.c 1225:port 3 attach sas addr is 3
drivers/scsi/mvsas/mv_sas.c 378:phy 3 byte dmaded.
drivers/scsi/mvsas/mv_sas.c 1585:mvs_I_T_nexus_reset for device[3]:rc= 0
ata12: translated ATA stat/err 0x01/04 to SCSI SK/ASC/ASCQ 0xb/00/00
ata12: status=0x01 { Error }
ata12: error=0x04 { DriveStatusError }

So it seems independent of the mdelay value.

Best regards,

Audiohaven / Frederic Vanden Poel

On Tue, Jun 29, 2010 at 2:16 PM, Srinivas Naga Venkatasatya
Pasagadugula - ERS, HCL Tech <satyasrinivasp@xxxxxx> wrote:
> Hi,
>
> As I didn't have time to give the proper fix for this delay, I have modified to mdelay (10) based on my testing.
>
> With the mdelay (100) every thing is working as expected?
>
> If so I have to modify the code in such a way that it has to reset all the ports in parallel and then the settle time.
>
> -Srini
>
> -----Original Message-----
> From: linux-scsi-owner@xxxxxxxxxxxxxxx [mailto:linux-scsi-owner@xxxxxxxxxxxxxxx] On Behalf Of Audio Haven
> Sent: Tuesday, June 29, 2010 5:17 PM
> To: Srinivas Naga Venkatasatya Pasagadugula - ERS, HCL Tech
> Cc: James Bottomley; linux-scsi@xxxxxxxxxxxxxxx
> Subject: Re: [PATCH] MVSAS: hot plug handling and IO issues
>
> Hello Srinivas,
>
> I have tested this patch with a stock 2.6.32.7 kernel on a x86_64
> running Centos 5.5.
> I have another box with 8 1TB disks in a raid6 config: 6 drives are
> SAMSUNG HD103SI, 2 drives are Hitachi HDT721010SLA360.
>
> I frequently get the following behaviour:
>
> A large file IO suddenly becomes very slow (eg watching a HDTV file
> over samba), then the following is then reported:
>
> drivers/scsi/mvsas/mv_sas.c 1631:mvs_query_task:rc= 5
> drivers/scsi/mvsas/mv_sas.c 1967:Release slot [2] tag[2], task
> [ffff880035138700]:
> drivers/scsi/mvsas/mv_sas.c 1967:Release slot [0] tag[0], task
> [ffff88003b436000]:
> drivers/scsi/mvsas/mv_sas.c 1967:Release slot [3] tag[3], task
> [ffff88003b4361c0]:
> drivers/scsi/mvsas/mv_sas.c 1967:Release slot [4] tag[4], task
> [ffff88003b436380]:
> drivers/scsi/mvsas/mv_sas.c 1967:Release slot [5] tag[5], task
> [ffff88003b436540]:
> drivers/scsi/mvsas/mv_sas.c 1585:mvs_I_T_nexus_reset for device[7]:rc= 0
> ata18: translated ATA stat/err 0x01/04 to SCSI SK/ASC/ASCQ 0xb/00/00
> ata18: status=0x01 { Error }
> ata18: error=0x04 { DriveStatusError }
> ata18: translated ATA stat/err 0x01/04 to SCSI SK/ASC/ASCQ 0xb/00/00
> ata18: status=0x01 { Error }
> ata18: error=0x04 { DriveStatusError }
> ata18: translated ATA stat/err 0x01/04 to SCSI SK/ASC/ASCQ 0xb/00/00
> ata18: status=0x01 { Error }
> ata18: error=0x04 { DriveStatusError }
> ata18: translated ATA stat/err 0x01/04 to SCSI SK/ASC/ASCQ 0xb/00/00
> ata18: status=0x01 { Error }
> ata18: error=0x04 { DriveStatusError }
> ata18: translated ATA stat/err 0x01/04 to SCSI SK/ASC/ASCQ 0xb/00/00
> ata18: status=0x01 { Error }
> ata18: error=0x04 { DriveStatusError }
> ata18: translated ATA stat/err 0x01/04 to SCSI SK/ASC/ASCQ 0xb/00/00
> ata18: status=0x01 { Error }
> ata18: error=0x04 { DriveStatusError }
> ata18: translated ATA stat/err 0x01/04 to SCSI SK/ASC/ASCQ 0xb/00/00
> ata18: status=0x01 { Error }
> ata18: error=0x04 { DriveStatusError }
>
> Now the disks are never kicked out of raid
>
> md2 : active raid6 sdl1[7] sde1[0] sdk1[6] sdj1[5] sdi1[4] sdh1[3]
> sdg1[2] sdf1[1]
>      5860558848 blocks super 1.2 level 6, 1024k chunk, algorithm 2
> [8/8] [UUUUUUUU]
>
> but anything running on this disk is halted and causes time outs. In
> the past all these drives were connected to my motherboards SATA ports
> as JBOD and they never failed or timed out. When connected to the
> Supermicro AOC-SASLP-MV8 using your latest patch with the 10ms delay,
> they sometimes timeout, which is difficult to predict.
>
> Best regards,
>
> Frederic Vanden Poel
> aka Audio Haven
>
> On Mon, Mar 8, 2010 at 1:58 PM, Srinivas Naga Venkatasatya
> Pasagadugula - ERS, HCL Tech <satyasrinivasp@xxxxxx> wrote:
>> James,
>>
>> Thanks a lot for reviewing this patch.
>>
>>>                       mvs_update_phyinfo (mvi, phy_no, 0);
>>> +                     if (phy->phy_type & PORT_TYPE_SAS) {
>>> +                             MVS_CHIP_DISP->phy_reset (mvi, phy_no, 2);
>>> +                             mdelay (100);
>>> +                     }
>>
>> I agree with your analysis on the same. Mainly I have added this piece of code for Tape issues. Here I used 100 ms delay which is not required, so I have changed to 10ms i.e mdelay (10). I didn't face any issues with devices after changing it to 10ms.
>> Please try to include this patch in RC tree. If required I will submit one more patch for the same by considering your suggestion i.e reset in parallel and then the settle time, but this requires a lot of testing to be done so it will take some time to submit the patch.
>>
>> NOTE: I have attached the patch (copied from below thread) which is having one change i.e mdelay (10).
>>
>> Thanks,
>> Srinivas.
>>
>> -----Original Message-----
>> From: James Bottomley [mailto:James.Bottomley@xxxxxxx]
>> Sent: Friday, March 05, 2010 4:17 PM
>> To: Srinivas Naga Venkatasatya Pasagadugula - ERS, HCL Tech
>> Cc: linux-scsi@xxxxxxxxxxxxxxx
>> Subject: Re: [PATCH] MVSAS: hot plug handling and IO issues
>>
>> On Tue, 2010-02-16 at 16:40 +0530, Srinivas Naga Venkatasatya
>> Pasagadugula - ERS, HCL Tech wrote:
>>> From: Srinivas <satyasrinivasp@xxxxxx>
>>> Date: Mon, 15 Feb 2010
>>
>> So, I'll add it, it seems to work based on the reports.
>>
>>> Subject: [PATCH]: Fix for hot plug handling and IO issues.
>>>       Added code for handling of hot-plugging drives and tape issues.
>>
>> This is a bit terse for a change like this.
>>
>>> Signed-off-by: Srinivas <satyasrinivasp@xxxxxx>
>>
>> This is the only bit that seems to have a serious technical problem:
>>
>>> @@ -2085,6 +2145,11 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
>>>                                                       phy_no, tmp);
>>>                       }
>>>                       mvs_update_phyinfo(mvi, phy_no, 0);
>>> +                     if (phy->phy_type & PORT_TYPE_SAS) {
>>> +                             MVS_CHIP_DISP->phy_reset(mvi, phy_no, 2);
>>> +                             mdelay(100);
>>> +                     }
>>> +
>>>                       mvs_bytes_dmaed(mvi, phy_no);
>>>                       /* whether driver is going to handle hot plug */
>>>                       if (phy->phy_event & PHY_PLUG_OUT) {
>>
>> It's doing a 100ms CPU spin for each port initialisation.  For an eight
>> port system, that's nearly a second, all of which is done with the
>> mvi->lock held.  In particular, this is done in the ISR on some systems,
>> so that's really going to add massive delays.
>>
>> It looks like this is just a bus settle time for the SAS ports, so
>> obviously they could all be reset in parallel and then the settle time
>> could be waited out (rather than doing each one in sequence), but
>> realistically even a single 100ms wait in an interrupt routine is too
>> long ... the port probably has to be marked as in reset somehow to avoid
>> this.
>>
>> Other than the above, there were a large number of checkpatch errors,
>> which I fixed:
>>
>> total: 58 errors, 19 warnings, 632 lines checked
>>
>> can you start with the patch below to carry these fixes forwards?
>>
>> Thanks,
>>
>> James
>>
>> ---
>>
>> diff --git a/drivers/scsi/mvsas/mv_64xx.c b/drivers/scsi/mvsas/mv_64xx.c
>> index 10a5077..afc7f6f 100644
>> --- a/drivers/scsi/mvsas/mv_64xx.c
>> +++ b/drivers/scsi/mvsas/mv_64xx.c
>> @@ -132,9 +132,9 @@ static void mvs_64xx_phy_reset(struct mvs_info *mvi, u32 phy_id, int hard)
>>        tmp &= ~PHYEV_RDY_CH;
>>        mvs_write_port_irq_stat(mvi, phy_id, tmp);
>>        tmp = mvs_read_phy_ctl(mvi, phy_id);
>> -       if (hard)
>> +       if (hard == 1)
>>                tmp |= PHY_RST_HARD;
>> -       else
>> +       else if (hard == 0)
>>                tmp |= PHY_RST;
>>        mvs_write_phy_ctl(mvi, phy_id, tmp);
>>        if (hard) {
>> @@ -144,6 +144,26 @@ static void mvs_64xx_phy_reset(struct mvs_info *mvi, u32 phy_id, int hard)
>>        }
>>  }
>>
>> +void mvs_64xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, u8 clear_all)
>> +{
>> +       void __iomem *regs = mvi->regs;
>> +       u32 tmp;
>> +       if (clear_all) {
>> +               tmp = mr32(MVS_INT_STAT_SRS_0);
>> +               if (tmp) {
>> +                       printk(KERN_DEBUG "check SRS 0 %08X.\n", tmp);
>> +                       mw32(MVS_INT_STAT_SRS_0, tmp);
>> +               }
>> +       } else {
>> +               tmp = mr32(MVS_INT_STAT_SRS_0);
>> +               if (tmp &  (1 << (reg_set % 32))) {
>> +                       printk(KERN_DEBUG "register set 0x%x was stopped.\n",
>> +                              reg_set);
>> +                       mw32(MVS_INT_STAT_SRS_0, 1 << (reg_set % 32));
>> +               }
>> +       }
>> +}
>> +
>>  static int __devinit mvs_64xx_chip_reset(struct mvs_info *mvi)
>>  {
>>        void __iomem *regs = mvi->regs;
>> @@ -761,6 +781,7 @@ const struct mvs_dispatch mvs_64xx_dispatch = {
>>        mvs_write_port_irq_mask,
>>        mvs_get_sas_addr,
>>        mvs_64xx_command_active,
>> +       mvs_64xx_clear_srs_irq,
>>        mvs_64xx_issue_stop,
>>        mvs_start_delivery,
>>        mvs_rx_update,
>> diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c
>> index cae6b2c..203ff93 100644
>> --- a/drivers/scsi/mvsas/mv_init.c
>> +++ b/drivers/scsi/mvsas/mv_init.c
>> @@ -37,6 +37,7 @@ static const struct mvs_chip_info mvs_chips[] = {
>>  };
>>
>>  #define SOC_SAS_NUM 2
>> +#define SG_MX 64
>>
>>  static struct scsi_host_template mvs_sht = {
>>        .module                 = THIS_MODULE,
>> @@ -53,10 +54,10 @@ static struct scsi_host_template mvs_sht = {
>>        .can_queue              = 1,
>>        .cmd_per_lun            = 1,
>>        .this_id                = -1,
>> -       .sg_tablesize           = SG_ALL,
>> +       .sg_tablesize           = SG_MX,
>>        .max_sectors            = SCSI_DEFAULT_MAX_SECTORS,
>>        .use_clustering         = ENABLE_CLUSTERING,
>> -       .eh_device_reset_handler        = sas_eh_device_reset_handler,
>> +       .eh_device_reset_handler = sas_eh_device_reset_handler,
>>        .eh_bus_reset_handler   = sas_eh_bus_reset_handler,
>>        .slave_alloc            = mvs_slave_alloc,
>>        .target_destroy         = sas_target_destroy,
>> @@ -65,19 +66,17 @@ static struct scsi_host_template mvs_sht = {
>>
>>  static struct sas_domain_function_template mvs_transport_ops = {
>>        .lldd_dev_found         = mvs_dev_found,
>> -       .lldd_dev_gone  = mvs_dev_gone,
>> -
>> +       .lldd_dev_gone          = mvs_dev_gone,
>>        .lldd_execute_task      = mvs_queue_command,
>>        .lldd_control_phy       = mvs_phy_control,
>>
>>        .lldd_abort_task        = mvs_abort_task,
>>        .lldd_abort_task_set    = mvs_abort_task_set,
>>        .lldd_clear_aca         = mvs_clear_aca,
>> -       .lldd_clear_task_set    = mvs_clear_task_set,
>> +       .lldd_clear_task_set    = mvs_clear_task_set,
>>        .lldd_I_T_nexus_reset   = mvs_I_T_nexus_reset,
>>        .lldd_lu_reset          = mvs_lu_reset,
>>        .lldd_query_task        = mvs_query_task,
>> -
>>        .lldd_port_formed       = mvs_port_formed,
>>        .lldd_port_deformed     = mvs_port_deformed,
>>
>> @@ -213,7 +212,11 @@ static irqreturn_t mvs_interrupt(int irq, void *opaque)
>>
>>  static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
>>  {
>> -       int i, slot_nr;
>> +       int i = 0, j = 0, slot_nr;
>> +       unsigned long buf_size;
>> +    void *buf;
>> +    dma_addr_t buf_dma;
>> +    struct mvs_slot_info *slot = 0;
>>
>>        if (mvi->flags & MVF_FLAG_SOC)
>>                slot_nr = MVS_SOC_SLOTS;
>> @@ -232,6 +235,7 @@ static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
>>                mvi->devices[i].dev_type = NO_DEVICE;
>>                mvi->devices[i].device_id = i;
>>                mvi->devices[i].dev_status = MVS_DEV_NORMAL;
>> +               init_timer(&mvi->devices[i].timer);
>>        }
>>
>>        /*
>> @@ -437,6 +441,7 @@ static int __devinit mvs_prep_sas_ha_init(struct Scsi_Host *shost,
>>
>>        sha->sas_phy = arr_phy;
>>        sha->sas_port = arr_port;
>> +       sha->core.shost = shost;
>>
>>        sha->lldd_ha = kzalloc(sizeof(struct mvs_prv_info), GFP_KERNEL);
>>        if (!sha->lldd_ha)
>> @@ -574,6 +579,10 @@ static int __devinit mvs_pci_init(struct pci_dev *pdev,
>>                }
>>                nhost++;
>>        } while (nhost < chip->n_host);
>> +#ifdef MVS_USE_TASKLET
>> +       tasklet_init(&mv_tasklet, mvs_tasklet,
>> +                    (unsigned long)SHOST_TO_SAS_HA(shost));
>> +#endif
>>
>>        mvs_post_sas_ha_init(shost, chip);
>>
>> diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
>> index 0d21386..4be7010 100644
>> --- a/drivers/scsi/mvsas/mv_sas.c
>> +++ b/drivers/scsi/mvsas/mv_sas.c
>> @@ -259,8 +259,6 @@ static inline void mvs_free_reg_set(struct mvs_info *mvi,
>>                mv_printk("device has been free.\n");
>>                return;
>>        }
>> -       if (dev->runing_req != 0)
>> -               return;
>>        if (dev->taskfileset == MVS_ID_NOT_MAPPED)
>>                return;
>>        MVS_CHIP_DISP->free_reg_set(mvi, &dev->taskfileset);
>> @@ -597,7 +595,7 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,
>>        struct mvs_slot_info *slot;
>>        void *buf_prd;
>>        u32 tag = tei->tag, hdr_tag;
>> -       u32 flags, del_q;
>> +       u32 flags, del_q, phy_mask;
>>        void *buf_tmp;
>>        u8 *buf_cmd, *buf_oaf;
>>        dma_addr_t buf_tmp_dma;
>> @@ -762,8 +760,6 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi,
>>        }
>>        if (is_tmf)
>>                flags |= (MCH_SSP_FR_TASK << MCH_SSP_FR_TYPE_SHIFT);
>> -       else
>> -               flags |= (MCH_SSP_FR_CMD << MCH_SSP_FR_TYPE_SHIFT);
>>        hdr->flags = cpu_to_le32(flags | (tei->n_elem << MCH_PRD_LEN_SHIFT));
>>        hdr->tags = cpu_to_le32(tag);
>>        hdr->data_len = cpu_to_le32(task->total_xfer_len);
>> @@ -878,14 +874,15 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
>>        struct mvs_slot_info *slot;
>>        u32 tag = 0xdeadbeef, rc, n_elem = 0;
>>        u32 n = num, pass = 0;
>> -       unsigned long flags = 0;
>> +       unsigned long flags = 0,  flags_libsas = 0;
>>
>>        if (!dev->port) {
>>                struct task_status_struct *tsm = &t->task_status;
>>
>>                tsm->resp = SAS_TASK_UNDELIVERED;
>>                tsm->stat = SAS_PHY_DOWN;
>> -               t->task_done(t);
>> +               if (dev->dev_type != SATA_DEV)
>> +                       t->task_done(t);
>>                return 0;
>>        }
>>
>> @@ -910,12 +907,24 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
>>                else
>>                        tei.port = &mvi->port[dev->port->id];
>>
>> -               if (!tei.port->port_attached) {
>> +               if (tei.port && !tei.port->port_attached) {
>>                        if (sas_protocol_ata(t->task_proto)) {
>>                                mv_dprintk("port %d does not"
>>                                        "attached device.\n", dev->port->id);
>> -                               rc = SAS_PHY_DOWN;
>> -                               goto out_done;
>> +                               struct task_status_struct *ts = &t->task_status;
>> +                               ts->stat = SAS_PROTO_RESPONSE;
>> +                               ts->stat = SAS_PHY_DOWN;
>> +                               spin_unlock_irqrestore(dev->sata_dev.ap->lock,
>> +                                                      flags_libsas);
>> +                               spin_unlock_irqrestore(&mvi->lock, flags);
>> +                               t->task_done(t);
>> +                               spin_lock_irqsave(&mvi->lock, flags);
>> +                               spin_lock_irqsave(dev->sata_dev.ap->lock,
>> +                                                 flags_libsas);
>> +                               if (n > 1)
>> +                                       t = list_entry(t->list.next,
>> +                                                      struct sas_task, list);
>> +                               continue;
>>                        } else {
>>                                struct task_status_struct *ts = &t->task_status;
>>                                ts->resp = SAS_TASK_UNDELIVERED;
>> @@ -973,8 +982,8 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
>>                        break;
>>                default:
>>                        dev_printk(KERN_ERR, mvi->dev,
>> -                               "unknown sas_task proto: 0x%x\n",
>> -                               t->task_proto);
>> +                                  "unknown sas_task proto: 0x%x\n",
>> +                                  t->task_proto);
>>                        rc = -EINVAL;
>>                        break;
>>                }
>> @@ -993,11 +1002,15 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
>>                spin_unlock(&t->task_state_lock);
>>
>>                mvs_hba_memory_dump(mvi, tag, t->task_proto);
>> -               mvi_dev->runing_req++;
>> +               mvi_dev->running_req++;
>>                ++pass;
>>                mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1);
>>                if (n > 1)
>>                        t = list_entry(t->list.next, struct sas_task, list);
>> +               if (likely(pass))
>> +                       MVS_CHIP_DISP->start_delivery(mvi, (mvi->tx_prod - 1) &
>> +                                                     (MVS_CHIP_SLOT_SZ - 1));
>> +
>>        } while (--n);
>>        rc = 0;
>>        goto out_done;
>> @@ -1012,10 +1025,6 @@ err_out:
>>                        dma_unmap_sg(mvi->dev, t->scatter, n_elem,
>>                                     t->data_dir);
>>  out_done:
>> -       if (likely(pass)) {
>> -               MVS_CHIP_DISP->start_delivery(mvi,
>> -                       (mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1));
>> -       }
>>        spin_unlock_irqrestore(&mvi->lock, flags);
>>        return rc;
>>  }
>> @@ -1187,7 +1196,7 @@ void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st)
>>                                MVS_CHIP_DISP->phy_reset(mvi, i, 0);
>>                                goto out_done;
>>                        }
>> -               }               else if (phy->phy_type & PORT_TYPE_SAS
>> +               }       else if (phy->phy_type & PORT_TYPE_SAS
>>                        || phy->att_dev_info & PORT_SSP_INIT_MASK) {
>>                        phy->phy_attached = 1;
>>                        phy->identify.device_type =
>> @@ -1256,7 +1265,20 @@ static void mvs_port_notify_formed(struct asd_sas_phy *sas_phy, int lock)
>>
>>  static void mvs_port_notify_deformed(struct asd_sas_phy *sas_phy, int lock)
>>  {
>> -       /*Nothing*/
>> +       struct domain_device *dev;
>> +       struct mvs_phy *phy = sas_phy->lldd_phy;
>> +       struct mvs_info *mvi = phy->mvi;
>> +       struct asd_sas_port *port = sas_phy->port;
>> +       int phy_no = 0;
>> +
>> +       while (phy != &mvi->phy[phy_no]) {
>> +               phy_no++;
>> +               if (phy_no >= MVS_MAX_PHYS)
>> +                       return;
>> +       }
>> +       list_for_each_entry(dev, &port->dev_list, dev_list_node)
>> +               mvs_do_release_task(phy->mvi, phy_no, NULL);
>> +
>>  }
>>
>>
>> @@ -1316,6 +1338,7 @@ int mvs_dev_found_notify(struct domain_device *dev, int lock)
>>                goto found_out;
>>        }
>>        dev->lldd_dev = mvi_device;
>> +       mvi_device->dev_status = MVS_DEV_NORMAL;
>>        mvi_device->dev_type = dev->dev_type;
>>        mvi_device->mvi_info = mvi;
>>        if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) {
>> @@ -1351,18 +1374,18 @@ int mvs_dev_found(struct domain_device *dev)
>>        return mvs_dev_found_notify(dev, 1);
>>  }
>>
>> -void mvs_dev_gone_notify(struct domain_device *dev, int lock)
>> +void mvs_dev_gone_notify(struct domain_device *dev)
>>  {
>>        unsigned long flags = 0;
>>        struct mvs_device *mvi_dev = dev->lldd_dev;
>>        struct mvs_info *mvi = mvi_dev->mvi_info;
>>
>> -       if (lock)
>> -               spin_lock_irqsave(&mvi->lock, flags);
>> +       spin_lock_irqsave(&mvi->lock, flags);
>>
>>        if (mvi_dev) {
>>                mv_dprintk("found dev[%d:%x] is gone.\n",
>>                        mvi_dev->device_id, mvi_dev->dev_type);
>> +               mvs_release_task(mvi, dev);
>>                mvs_free_reg_set(mvi, mvi_dev);
>>                mvs_free_dev(mvi_dev);
>>        } else {
>> @@ -1370,14 +1393,13 @@ void mvs_dev_gone_notify(struct domain_device *dev, int lock)
>>        }
>>        dev->lldd_dev = NULL;
>>
>> -       if (lock)
>>                spin_unlock_irqrestore(&mvi->lock, flags);
>>  }
>>
>>
>>  void mvs_dev_gone(struct domain_device *dev)
>>  {
>> -       mvs_dev_gone_notify(dev, 1);
>> +       mvs_dev_gone_notify(dev);
>>  }
>>
>>  static  struct sas_task *mvs_alloc_task(void)
>> @@ -1540,7 +1562,7 @@ int mvs_lu_reset(struct domain_device *dev, u8 *lun)
>>                num = mvs_find_dev_phyno(dev, phyno);
>>                spin_lock_irqsave(&mvi->lock, flags);
>>                for (i = 0; i < num; i++)
>> -                       mvs_release_task(mvi, phyno[i], dev);
>> +                       mvs_release_task(mvi, dev);
>>                spin_unlock_irqrestore(&mvi->lock, flags);
>>        }
>>        /* If failed, fall-through I_T_Nexus reset */
>> @@ -1552,8 +1574,8 @@ int mvs_lu_reset(struct domain_device *dev, u8 *lun)
>>  int mvs_I_T_nexus_reset(struct domain_device *dev)
>>  {
>>        unsigned long flags;
>> -       int i, phyno[WIDE_PORT_MAX_PHY], num , rc = TMF_RESP_FUNC_FAILED;
>> -       struct mvs_device * mvi_dev = (struct mvs_device *)dev->lldd_dev;
>> +       int rc = TMF_RESP_FUNC_FAILED;
>> +    struct mvs_device * mvi_dev = (struct mvs_device *)dev->lldd_dev;
>>        struct mvs_info *mvi = mvi_dev->mvi_info;
>>
>>        if (mvi_dev->dev_status != MVS_DEV_EH)
>> @@ -1563,10 +1585,8 @@ int mvs_I_T_nexus_reset(struct domain_device *dev)
>>                __func__, mvi_dev->device_id, rc);
>>
>>        /* housekeeper */
>> -       num = mvs_find_dev_phyno(dev, phyno);
>>        spin_lock_irqsave(&mvi->lock, flags);
>> -       for (i = 0; i < num; i++)
>> -               mvs_release_task(mvi, phyno[i], dev);
>> +       mvs_release_task(mvi, dev);
>>        spin_unlock_irqrestore(&mvi->lock, flags);
>>
>>        return rc;
>> @@ -1603,6 +1623,9 @@ int mvs_query_task(struct sas_task *task)
>>                case TMF_RESP_FUNC_FAILED:
>>                case TMF_RESP_FUNC_COMPLETE:
>>                        break;
>> +               default:
>> +                       rc = TMF_RESP_FUNC_COMPLETE;
>> +                       break;
>>                }
>>        }
>>        mv_printk("%s:rc= %d\n", __func__, rc);
>> @@ -1621,8 +1644,11 @@ int mvs_abort_task(struct sas_task *task)
>>        unsigned long flags;
>>        u32 tag;
>>
>> -       if (mvi->exp_req)
>> -               mvi->exp_req--;
>> +       if (!mvi_dev) {
>> +               mv_printk("%s:%d TMF_RESP_FUNC_FAILED\n", __func__, __LINE__);
>> +               rc = TMF_RESP_FUNC_FAILED;
>> +       }
>> +
>>        spin_lock_irqsave(&task->task_state_lock, flags);
>>        if (task->task_state_flags & SAS_TASK_STATE_DONE) {
>>                spin_unlock_irqrestore(&task->task_state_lock, flags);
>> @@ -1630,6 +1656,7 @@ int mvs_abort_task(struct sas_task *task)
>>                goto out;
>>        }
>>        spin_unlock_irqrestore(&task->task_state_lock, flags);
>> +       mvi_dev->dev_status = MVS_DEV_EH;
>>        if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) {
>>                struct scsi_cmnd * cmnd = (struct scsi_cmnd *)task->uldd_task;
>>
>> @@ -1654,12 +1681,31 @@ int mvs_abort_task(struct sas_task *task)
>>                        if (task->lldd_task) {
>>                                slot = task->lldd_task;
>>                                slot_no = (u32) (slot - mvi->slot_info);
>> +                               spin_lock_irqsave(&mvi->lock, flags);
>>                                mvs_slot_complete(mvi, slot_no, 1);
>> +                               spin_unlock_irqrestore(&mvi->lock, flags);
>>                        }
>>                }
>> +
>>        } else if (task->task_proto & SAS_PROTOCOL_SATA ||
>>                task->task_proto & SAS_PROTOCOL_STP) {
>>                /* to do free register_set */
>> +               if (SATA_DEV == dev->dev_type) {
>> +                       struct mvs_slot_info *slot = task->lldd_task;
>> +                       struct task_status_struct *tstat;
>> +                       u32 slot_idx = (u32)(slot - mvi->slot_info);
>> +                       tstat = &task->task_status;
>> +                       mv_dprintk(KERN_DEBUG "mv_abort_task() mvi=%p task=%p "
>> +                                  "slot=%p slot_idx=x%x\n",
>> +                                  mvi, task, slot, slot_idx);
>> +                       tstat->stat = SAS_ABORTED_TASK;
>> +                       if (mvi_dev && mvi_dev->running_req)
>> +                               mvi_dev->running_req--;
>> +                       if (sas_protocol_ata(task->task_proto))
>> +                               mvs_free_reg_set(mvi, mvi_dev);
>> +                       mvs_slot_task_free(mvi, task, slot, slot_idx);
>> +                       return -1;
>> +               }
>>        } else {
>>                /* SMP */
>>
>> @@ -1717,8 +1763,13 @@ static int mvs_sata_done(struct mvs_info *mvi, struct sas_task *task,
>>               SATA_RECEIVED_D2H_FIS(mvi_dev->taskfileset),
>>               sizeof(struct dev_to_host_fis));
>>        tstat->buf_valid_size = sizeof(*resp);
>> -       if (unlikely(err))
>> -               stat = SAS_PROTO_RESPONSE;
>> +       if (unlikely(err)) {
>> +               if (unlikely(err & CMD_ISS_STPD))
>> +                       stat = SAS_OPEN_REJECT;
>> +               else
>> +                       stat = SAS_PROTO_RESPONSE;
>> +       }
>> +
>>        return stat;
>>  }
>>
>> @@ -1728,6 +1779,7 @@ static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,
>>        struct mvs_slot_info *slot = &mvi->slot_info[slot_idx];
>>        int stat;
>>        u32 err_dw0 = le32_to_cpu(*(u32 *) (slot->response));
>> +       u32 err_dw1 = le32_to_cpu(*((u32 *)slot->response+1));
>>        u32 tfs = 0;
>>        enum mvs_port_type type = PORT_TYPE_SAS;
>>
>> @@ -1753,9 +1805,7 @@ static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,
>>                        mv_printk("find reserved error, why?\n");
>>
>>                task->ata_task.use_ncq = 0;
>> -               stat = SAS_PROTO_RESPONSE;
>> -               mvs_sata_done(mvi, task, slot_idx, 1);
>> -
>> +               mvs_sata_done(mvi, task, slot_idx, err_dw0);
>>        }
>>                break;
>>        default:
>> @@ -1772,18 +1822,20 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
>>        struct sas_task *task = slot->task;
>>        struct mvs_device *mvi_dev = NULL;
>>        struct task_status_struct *tstat;
>> +       struct domain_device *dev;
>> +       u32 aborted;
>>
>> -       bool aborted;
>>        void *to;
>>        enum exec_status sts;
>>
>>        if (mvi->exp_req)
>>                mvi->exp_req--;
>> -       if (unlikely(!task || !task->lldd_task))
>> +       if (unlikely(!task || !task->lldd_task || !task->dev))
>>                return -1;
>>
>>        tstat = &task->task_status;
>> -       mvi_dev = task->dev->lldd_dev;
>> +       dev = task->dev;
>> +       mvi_dev = dev->lldd_dev;
>>
>>        mvs_hba_cq_dump(mvi);
>>
>> @@ -1800,8 +1852,8 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
>>
>>        if (unlikely(aborted)) {
>>                tstat->stat = SAS_ABORTED_TASK;
>> -               if (mvi_dev)
>> -                       mvi_dev->runing_req--;
>> +               if (mvi_dev && mvi_dev->running_req)
>> +                       mvi_dev->running_req--;
>>                if (sas_protocol_ata(task->task_proto))
>>                        mvs_free_reg_set(mvi, mvi_dev);
>>
>> @@ -1809,24 +1861,17 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
>>                return -1;
>>        }
>>
>> -       if (unlikely(!mvi_dev || !slot->port->port_attached || flags)) {
>> -               mv_dprintk("port has not device.\n");
>> +       if (unlikely(!mvi_dev || flags)) {
>> +               if (!mvi_dev)
>> +                       mv_dprintk("port has not device.\n");
>>                tstat->stat = SAS_PHY_DOWN;
>>                goto out;
>>        }
>>
>> -       /*
>> -       if (unlikely((rx_desc & RXQ_ERR) || (*(u64 *) slot->response))) {
>> -                mv_dprintk("Find device[%016llx] RXQ_ERR %X,
>> -                err info:%016llx\n",
>> -                SAS_ADDR(task->dev->sas_addr),
>> -                rx_desc, (u64)(*(u64 *) slot->response));
>> -       }
>> -       */
>> -
>>        /* error info record present */
>>        if (unlikely((rx_desc & RXQ_ERR) && (*(u64 *) slot->response))) {
>>                tstat->stat = mvs_slot_err(mvi, task, slot_idx);
>> +               tstat->resp = SAS_TASK_COMPLETE;
>>                goto out;
>>        }
>>
>> @@ -1868,11 +1913,16 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
>>                tstat->stat = SAM_CHECK_COND;
>>                break;
>>        }
>> +       if (!slot->port->port_attached) {
>> +               mv_dprintk("port %d has removed.\n", slot->port->sas_port.id);
>> +               tstat->stat = SAS_PHY_DOWN;
>> +       }
>> +
>>
>>  out:
>> -       if (mvi_dev) {
>> -               mvi_dev->runing_req--;
>> -               if (sas_protocol_ata(task->task_proto))
>> +       if (mvi_dev && mvi_dev->running_req) {
>> +               mvi_dev->running_req--;
>> +               if (sas_protocol_ata(task->task_proto) && !mvi_dev->running_req)
>>                        mvs_free_reg_set(mvi, mvi_dev);
>>        }
>>        mvs_slot_task_free(mvi, task, slot, slot_idx);
>> @@ -1888,10 +1938,10 @@ out:
>>        return sts;
>>  }
>>
>> -void mvs_release_task(struct mvs_info *mvi,
>> +void mvs_do_release_task(struct mvs_info *mvi,
>>                int phy_no, struct domain_device *dev)
>>  {
>> -       int i = 0; u32 slot_idx;
>> +       u32 slot_idx;
>>        struct mvs_phy *phy;
>>        struct mvs_port *port;
>>        struct mvs_slot_info *slot, *slot2;
>> @@ -1900,6 +1950,10 @@ void mvs_release_task(struct mvs_info *mvi,
>>        port = phy->port;
>>        if (!port)
>>                return;
>> +       /* clean cmpl queue in case request is already finished */
>> +       mvs_int_rx(mvi, false);
>> +
>> +
>>
>>        list_for_each_entry_safe(slot, slot2, &port->list, entry) {
>>                struct sas_task *task;
>> @@ -1911,18 +1965,22 @@ void mvs_release_task(struct mvs_info *mvi,
>>
>>                mv_printk("Release slot [%x] tag[%x], task [%p]:\n",
>>                        slot_idx, slot->slot_tag, task);
>> -
>> -               if (task->task_proto & SAS_PROTOCOL_SSP) {
>> -                       mv_printk("attached with SSP task CDB[");
>> -                       for (i = 0; i < 16; i++)
>> -                               mv_printk(" %02x", task->ssp_task.cdb[i]);
>> -                       mv_printk(" ]\n");
>> -               }
>> +               MVS_CHIP_DISP->command_active(mvi, slot_idx);
>>
>>                mvs_slot_complete(mvi, slot_idx, 1);
>>        }
>>  }
>>
>> +void mvs_release_task(struct mvs_info *mvi,
>> +                     struct domain_device *dev)
>> +{
>> +       int i, phyno[WIDE_PORT_MAX_PHY], num;
>> +       /* housekeeper */
>> +       num = mvs_find_dev_phyno(dev, phyno);
>> +       for (i = 0; i < num; i++)
>> +               mvs_do_release_task(mvi, phyno[i], dev);
>> +}
>> +
>>  static void mvs_phy_disconnected(struct mvs_phy *phy)
>>  {
>>        phy->phy_attached = 0;
>> @@ -2029,16 +2087,18 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
>>        * we need check the interrupt status which belongs to per port.
>>        */
>>
>> -       if (phy->irq_status & PHYEV_DCDR_ERR)
>> +       if (phy->irq_status & PHYEV_DCDR_ERR) {
>>                mv_dprintk("port %d STP decoding error.\n",
>> -               phy_no+mvi->id*mvi->chip->n_phy);
>> +               phy_no + mvi->id*mvi->chip->n_phy);
>> +       }
>>
>>        if (phy->irq_status & PHYEV_POOF) {
>>                if (!(phy->phy_event & PHY_PLUG_OUT)) {
>>                        int dev_sata = phy->phy_type & PORT_TYPE_SATA;
>>                        int ready;
>> -                       mvs_release_task(mvi, phy_no, NULL);
>> +                       mvs_do_release_task(mvi, phy_no, NULL);
>>                        phy->phy_event |= PHY_PLUG_OUT;
>> +                       MVS_CHIP_DISP->clear_srs_irq(mvi, 0, 1);
>>                        mvs_handle_event(mvi,
>>                                (void *)(unsigned long)phy_no,
>>                                PHY_PLUG_EVENT);
>> @@ -2085,6 +2145,11 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
>>                                                        phy_no, tmp);
>>                        }
>>                        mvs_update_phyinfo(mvi, phy_no, 0);
>> +                       if (phy->phy_type & PORT_TYPE_SAS) {
>> +                               MVS_CHIP_DISP->phy_reset(mvi, phy_no, 2);
>> +                               mdelay(100);
>> +                       }
>> +
>>                        mvs_bytes_dmaed(mvi, phy_no);
>>                        /* whether driver is going to handle hot plug */
>>                        if (phy->phy_event & PHY_PLUG_OUT) {
>> diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h
>> index aa2270a..85b79c7 100644
>> --- a/drivers/scsi/mvsas/mv_sas.h
>> +++ b/drivers/scsi/mvsas/mv_sas.h
>> @@ -38,6 +38,7 @@
>>  #include <linux/irq.h>
>>  #include <linux/vmalloc.h>
>>  #include <scsi/libsas.h>
>> +#include <scsi/scsi.h>
>>  #include <scsi/scsi_tcq.h>
>>  #include <scsi/sas_ata.h>
>>  #include <linux/version.h>
>> @@ -48,7 +49,7 @@
>>  #define _MV_DUMP               0
>>  #define MVS_ID_NOT_MAPPED      0x7f
>>  /* #define DISABLE_HOTPLUG_DMA_FIX */
>> -#define MAX_EXP_RUNNING_REQ    2
>> +// #define MAX_EXP_RUNNING_REQ 2
>>  #define WIDE_PORT_MAX_PHY              4
>>  #define        MV_DISABLE_NCQ  0
>>  #define mv_printk(fmt, arg ...)        \
>> @@ -128,6 +129,7 @@ struct mvs_dispatch {
>>
>>        void (*get_sas_addr)(void *buf, u32 buflen);
>>        void (*command_active)(struct mvs_info *mvi, u32 slot_idx);
>> +       void (*clear_srs_irq)(struct mvs_info *mvi, u8 reg_set, u8 clear_all);
>>        void (*issue_stop)(struct mvs_info *mvi, enum mvs_port_type type,
>>                                u32 tfs);
>>        void (*start_delivery)(struct mvs_info *mvi, u32 tx);
>> @@ -235,9 +237,10 @@ struct mvs_device {
>>        enum sas_dev_type dev_type;
>>        struct mvs_info *mvi_info;
>>        struct domain_device *sas_device;
>> +       struct timer_list timer;
>>        u32 attached_phy;
>>        u32 device_id;
>> -       u32 runing_req;
>> +       u32 running_req;
>>        u8 taskfileset;
>>        u8 dev_status;
>>        u16 reserved;
>> @@ -396,7 +399,9 @@ int mvs_lu_reset(struct domain_device *dev, u8 *lun);
>>  int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags);
>>  int mvs_I_T_nexus_reset(struct domain_device *dev);
>>  int mvs_query_task(struct sas_task *task);
>> -void mvs_release_task(struct mvs_info *mvi, int phy_no,
>> +void mvs_release_task(struct mvs_info *mvi,
>> +                       struct domain_device *dev);
>> +void mvs_do_release_task(struct mvs_info *mvi, int phy_no,
>>                        struct domain_device *dev);
>>  void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events);
>>  void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st);
>>
>>
>>
>> DISCLAIMER:
>> -----------------------------------------------------------------------------------------------------------------------
>>
>> The contents of this e-mail and any attachment(s) are confidential and intended for the named recipient(s) only.
>> It shall not attach any liability on the originator or HCL or its affiliates. Any views or opinions presented in
>> this email are solely those of the author and may not necessarily reflect the opinions of HCL or its affiliates.
>> Any form of reproduction, dissemination, copying, disclosure, modification, distribution and / or publication of
>> this message without the prior written consent of the author of this e-mail is strictly prohibited. If you have
>> received this email in error please delete it and notify the sender immediately. Before opening any mail and
>> attachments please check them for viruses and defect.
>>
>> -----------------------------------------------------------------------------------------------------------------------
>>
>
> --
> 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