MVSAS: Enhanced hot plug handling
PATCH 6/7 MVSAS: Enhanced hot plug handling
Quoted 2 lines
From
894361e5503f4ddc9a073173e2e3942fd7f40905Mon Sep 17 00:00:00 2001
From: Andy <[email protected]>
Date: Fri, 6 Nov 2009 17:33:49 +0800
Subject: [PATCH 6/7] bug fix with hot plug.
Add code to make the disk IO more stable when hot plug disk, and refined some code with usage of HW resource,enhanced error checking.
--- drivers/scsi/mvsas/mv_64xx.c | 27 ++++- drivers/scsi/mvsas/mv_94xx.c | 146 +++++++++++++++---- drivers/scsi/mvsas/mv_init.c | 28 +++- drivers/scsi/mvsas/mv_sas.c | 320 ++++++++++++++++++++++++++++------------- drivers/scsi/mvsas/mv_sas.h | 14 ++- 5 files changed, 389 insertions(+), 146 deletions(-)
drivers/scsi/mvsas/mv_64xx.c +25 -2
@@ -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) {
@@ -487,6 +487,28 @@ static void mvs_64xx_command_active(struct mvs_info *mvi, u32 slot_idx) }while (tmp &1 << (slot_idx %32 )); } +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) { +mv_printk ("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 ))) { +mv_printk ("register set 0x%x was stopped.\n" , reg_set); +mw32 (MVS_INT_STAT_SRS_0 ,1 << (reg_set %32 )); + } + } +} + +static void mvs_64xx_issue_stop (struct mvs_info *mvi,enum mvs_port_type type,u32 tfs) {
@@ -769,6 +791,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,
drivers/scsi/mvsas/mv_94xx.c +115 -31
218 lines not on this page · raw message
drivers/scsi/mvsas/mv_init.c +21 -7
@@ -82,7 +82,7 @@ static struct sas_domain_function_template mvs_transport_ops = { .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,
@@ -190,9 +190,9 @@ static void mvs_tasklet(unsigned long opaque)for (i =0 ; i < core_nr; i++) { mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i]; - stat =MVS_CHIP_DISP ->isr_status (mvi, mvi->irq); + stat =MVS_CHIP_DISP ->isr_status (mvi, mvi->pdev->irq);if (stat) -MVS_CHIP_DISP ->isr (mvi, mvi->irq, stat); +MVS_CHIP_DISP ->isr (mvi, mvi->pdev->irq, stat); } }
@@ -252,7 +252,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 ;
@@ -266,11 +270,13 @@ static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost) mvi->port[i].port_attached =0 ;INIT_LIST_HEAD (&mvi->port[i].list); } +for (i =0 ; i <MVS_MAX_DEVICES ; i++) { mvi->devices[i].taskfileset =MVS_ID_NOT_MAPPED ; 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); }/*
@@ -279,11 +285,13 @@ static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost) mvi->tx =dma_alloc_coherent (mvi->dev,sizeof (*mvi->tx) *MVS_CHIP_SLOT_SZ , &mvi->tx_dma,GFP_KERNEL ); +if (!mvi->tx) goto err_out;memset (mvi->tx,0 ,sizeof (*mvi->tx) *MVS_CHIP_SLOT_SZ ); mvi->rx_fis =dma_alloc_coherent (mvi->dev,MVS_RX_FISL_SZ , &mvi->rx_fis_dma,GFP_KERNEL ); +if (!mvi->rx_fis) goto err_out;memset (mvi->rx_fis,0 ,MVS_RX_FISL_SZ );
@@ -291,6 +299,7 @@ static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost) mvi->rx =dma_alloc_coherent (mvi->dev,sizeof (*mvi->rx) * (MVS_RX_RING_SZ +1 ), &mvi->rx_dma,GFP_KERNEL ); +if (!mvi->rx) goto err_out;memset (mvi->rx,0 ,sizeof (*mvi->rx) * (MVS_RX_RING_SZ +1 ));
@@ -300,6 +309,7 @@ static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost) mvi->slot =dma_alloc_coherent (mvi->dev,sizeof (*mvi->slot) * slot_nr, &mvi->slot_dma,GFP_KERNEL ); +if (!mvi->slot) goto err_out;memset (mvi->slot,0 ,sizeof (*mvi->slot) * slot_nr);
@@ -421,7 +431,6 @@ static struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev, mvi->chip_id = ent->driver_data; mvi->chip = &mvs_chips[mvi->chip_id];INIT_LIST_HEAD (&mvi->wq_list); - mvi->irq = pdev->irq; ((struct mvs_prv_info *)sha->lldd_ha)->mvi[id] = mvi; ((struct mvs_prv_info *)sha->lldd_ha)->n_phy = mvi->chip->n_phy;
@@ -496,6 +505,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)
@@ -504,7 +514,7 @@ static int __devinit mvs_prep_sas_ha_init(struct Scsi_Host *shost, ((struct mvs_prv_info *)sha->lldd_ha)->n_host = core_nr; shost->transportt = mvs_stt; - shost->max_id =128 ; + shost->max_id =MVS_MAX_DEVICES ; shost->max_lun = ~0 ; shost->max_channel =1 ; shost->max_cmd_len =16 ;
@@ -639,6 +649,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);
@@ -699,7 +713,7 @@ static void __devexit mvs_pci_remove(struct pci_dev *pdev)scsi_remove_host (mvi->shost);MVS_CHIP_DISP ->interrupt_disable (mvi); -free_irq (mvi->irq, sha); +free_irq (mvi->pdev->irq, sha);if (mvi->flags &MVF_MSI ) {mvs_disable_msi (mvi);pci_disable_msi (pdev);
drivers/scsi/mvsas/mv_sas.c +218 -102
660 lines not on this page · raw message
drivers/scsi/mvsas/mv_sas.h +10 -4
@@ -38,17 +38,17 @@#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> #include "mv_defs.h" #define DRV_NAME "mvsas" -#define DRV_VERSION "0.8.2" +#define DRV_VERSION "0.8.9"#define _MV_DUMP 0#define MVS_ID_NOT_MAPPED 0x7f/* #define DISABLE_HOTPLUG_DMA_FIX */ -#define MAX_EXP_RUNNING_REQ 2#define WIDE_PORT_MAX_PHY 4#define MV_DISABLE_NCQ 0 #define mv_printk(fmt, arg ...) \
@@ -130,6 +130,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);
@@ -240,9 +241,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;
@@ -391,6 +393,8 @@ void mvs_scan_start(struct Scsi_Host *shost);int mvs_scan_finished (struct Scsi_Host *shost,unsigned long time);int mvs_queue_command (struct sas_task *task,const int num,gfp_t gfp_flags); +void mvs_set_sense (u8 *buffer,int len,int d_sense, +int key,int asc,int ascq);int mvs_abort_task (struct sas_task *task);int mvs_abort_task_set (struct domain_device *dev,u8 *lun);int mvs_clear_aca (struct domain_device *dev,u8 *lun);
@@ -403,7 +407,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_do_release_task (struct mvs_info *mvi, +int phy_no,struct domain_device *dev); +void mvs_release_task (struct mvs_info *mvi,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);
Signature · 1 line
1.6.2.2
@@ -914,13 +911,22 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
tei.port = &mvi->port[dev->port->id -mvi->chip->n_phy];
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;
[Jack] Here ts->stat was double set. Maybe the first one is unnessary.
+
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);
[Jack] Is there something wrong with the the lock sequence . for sata io path, will __acquires(dev->sata_dev.ap->lock) when issue cmd to lldd
and you acquires your mvi lock then, so should you change the lock sequence to :
spin_unlock_irqrestore(&mvi->lock, flags);
spin_unlock_irqrestore(dev->sata_dev.ap->lock,
flags_libsas); t->task_done(t); spin_lock_irqsave(dev->sata_dev.ap->lock, flags_libsas);
spin_lock_irqsave(&mvi->lock, flags);