MVSAS:add supporting MSI feature
PATCH 2/7 MVSAS:add supporting MSI feature
Quoted 2 lines
From
8b51aa63e8b123046a334d630ae045f479acbf6cMon Sep 17 00:00:00 2001
From: andy <[email protected]>
Date: Fri, 6 Nov 2009 17:03:21 +0800
Subject: [PATCH 2/7] Add supporting MSI feature
MSI feature is implemented with mvsas driver.
--- drivers/scsi/mvsas/mv_init.c | 113 ++++++++++++++++++++++++++++++++++++++++-- drivers/scsi/mvsas/mv_sas.c | 28 ++++++----- drivers/scsi/mvsas/mv_sas.h | 2 + 3 files changed, 126 insertions(+), 17 deletions(-)
drivers/scsi/mvsas/mv_init.c +109 -4
@@ -25,6 +25,10 @@#include "mv_sas.h" +static int msi; +module_param (msi, int,0 ); +MODULE_PARM_DESC (msi,"Enable Message Signaled Interrupts(0=off, 1=on)" ); +int io_delay;static struct scsi_transport_template *mvs_stt;static const struct mvs_chip_info mvs_chips[] = { [chip_6320] = {1 ,2 ,0x400 ,17 ,16 ,9 , &mvs_64xx_dispatch, },
@@ -36,11 +40,13 @@ static const struct mvs_chip_info mvs_chips[] = { [chip_1320] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, }, }; +struct device_attribute *mvst_host_attrs[];#define SOC_SAS_NUM 2static struct scsi_host_template mvs_sht = { .module =THIS_MODULE , - .name =DRV_NAME , + .name ="Marvell Storage Controller" , + .proc_name =DRV_NAME , .queuecommand = sas_queuecommand, .target_alloc = sas_target_alloc, .slave_configure = mvs_slave_configure,
@@ -61,6 +67,7 @@ static struct scsi_host_template mvs_sht = { .slave_alloc = mvs_slave_alloc, .target_destroy = sas_target_destroy, .ioctl = sas_ioctl, + .shost_attrs = mvst_host_attrs, };static struct sas_domain_function_template mvs_transport_ops = {
@@ -89,6 +96,7 @@ static void __devinit mvs_phy_init(struct mvs_info *mvi, int phy_id)struct asd_sas_phy *sas_phy = &phy->sas_phy; phy->mvi = mvi; + phy->port =NULL ;init_timer (&phy->timer); sas_phy->enabled = (phy_id < mvi->chip->n_phy) ?1 :0 ; sas_phy->class =SAS ;
@@ -118,7 +126,7 @@ static void mvs_free(struct mvs_info *mvi)if (mvi->flags &MVF_FLAG_SOC ) slot_nr =MVS_SOC_SLOTS ;else - slot_nr =MVS_SLOTS ; + slot_nr =MVS_CHIP_SLOT_SZ ;for (i =0 ; i < mvi->tags_num; i++) {struct mvs_slot_info *slot = &mvi->slot_info[i];
@@ -183,6 +191,30 @@ static void mvs_tasklet(unsigned long opaque) }#endif +void mvs_enable_msi (struct mvs_info *mvi) +{ +u32 tmp; +pci_read_config_dword (mvi->pdev,PCR_CMD , &tmp); + tmp |=1 <<10 ;/* disable interrupt */ +pci_write_config_dword (mvi->pdev,PCR_CMD , tmp); + +pci_read_config_dword (mvi->pdev,PCR_MSI_CTRL , &tmp); + tmp |=1 <<16 ;/* enable MSI */ +pci_write_config_dword (mvi->pdev,PCR_MSI_CTRL , tmp); +} +void mvs_disable_msi (struct mvs_info *mvi) +{ +u32 tmp; +pci_read_config_dword (mvi->pdev,PCR_CMD , &tmp); + tmp &= ~(1 <<10 );/* enable interrupt */ +pci_write_config_dword (mvi->pdev,PCR_CMD , tmp); + +pci_read_config_dword (mvi->pdev,PCR_MSI_CTRL , &tmp); + tmp &= ~(1 <<16 );/* disable MSI */ +pci_write_config_dword (mvi->pdev,PCR_MSI_CTRL , tmp); +} + +static irqreturn_t mvs_interrupt (int irq,void *opaque) {u32 core_nr, i =0 ;
@@ -519,6 +551,7 @@ static int __devinit mvs_pci_init(struct pci_dev *pdev,dev_printk (KERN_INFO , &pdev->dev,"mvsas: driver version %s\n" ,DRV_VERSION ); + io_delay =0 ; rc =pci_enable_device (pdev);if (rc) goto err_out_enable;
@@ -563,6 +596,8 @@ static int __devinit mvs_pci_init(struct pci_dev *pdev, rc = -ENOMEM ; goto err_out_regions; } +if (msi) + mvi->flags |=MVF_MSI ;mvs_init_sas_add (mvi);
@@ -581,13 +616,22 @@ static int __devinit mvs_pci_init(struct pci_dev *pdev,if (rc) goto err_out_shost; +if (mvi->flags &MVF_MSI ) { +pci_enable_msi (pdev); +mvs_enable_msi (mvi); + } rc =sas_register_ha (SHOST_TO_SAS_HA (shost));if (rc) goto err_out_shost; rc =request_irq (pdev->irq, irq_handler,IRQF_SHARED ,DRV_NAME ,SHOST_TO_SAS_HA (shost)); -if (rc) +if (rc) { +if (mvi->flags &MVF_MSI ) { +mvs_disable_msi (mvi); +pci_disable_msi (pdev); + } goto err_not_sas; + }MVS_CHIP_DISP ->interrupt_enable (mvi);
@@ -620,13 +664,16 @@ static void __devexit mvs_pci_remove(struct pci_dev *pdev)tasklet_kill (&mv_tasklet);#endif -pci_set_drvdata (pdev,NULL );sas_unregister_ha (sha);sas_remove_host (mvi->shost);scsi_remove_host (mvi->shost);MVS_CHIP_DISP ->interrupt_disable (mvi);free_irq (mvi->irq, sha); +if (mvi->flags &MVF_MSI ) { +mvs_disable_msi (mvi); +pci_disable_msi (pdev); + }for (i =0 ; i < core_nr; i++) { mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i];mvs_free (mvi);
@@ -634,6 +681,7 @@ static void __devexit mvs_pci_remove(struct pci_dev *pdev)kfree (sha->sas_phy);kfree (sha->sas_port);kfree (sha); +pci_set_drvdata (pdev,NULL );pci_release_regions (pdev);pci_disable_device (pdev);return ;
@@ -668,6 +716,57 @@ static struct pci_driver mvs_pci_driver = { .remove = __devexit_p(mvs_pci_remove), }; +static ssize_t +mvs_show_driver_version (struct device *cdev, +struct device_attribute *attr, +char *buffer) +{ +return snprintf (buffer,PAGE_SIZE ,"%s\n" ,DRV_VERSION ); +} + +static DEVICE_ATTR(driver_version, + S_IRUGO, + mvs_show_driver_version, + NULL); + +static ssize_t +mvs_store_io_delay (struct device *cdev, +struct device_attribute *attr, +const char *buffer,size_t size) +{ + +int val =0 ; + +if (buffer ==NULL ) +return size; + +if (sscanf (buffer,"%d" , &val) !=1 ) +return -EINVAL ; + + io_delay = val; +if (io_delay >10 ) { +printk (KERN_NOTICE "io delay time %d seconds is too long, \ +max is 10s\n" , io_delay); + io_delay =10 ; +return strlen (buffer); + } +printk (KERN_NOTICE "set io delay time to %d seconds\n" , io_delay); +return strlen (buffer); +} + +static ssize_t mvs_show_io_delay (struct device *cdev, +struct device_attribute *attr, +char *buffer) +{ +return snprintf (buffer,PAGE_SIZE ,"%d\n" , io_delay); +} + + +static DEVICE_ATTR(io_delay, + S_IRUGO|S_IWUSR, + mvs_show_io_delay, + mvs_store_io_delay); +/* task handler */ struct task_struct *mvs_th;static int __init mvs_init (void )
@@ -695,6 +794,12 @@ static void __exit mvs_exit(void)sas_release_transport (mvs_stt); } +struct device_attribute *mvst_host_attrs[] = { + &dev_attr_driver_version, + &dev_attr_io_delay, +NULL , +}; +module_init (mvs_init);module_exit (mvs_exit);
drivers/scsi/mvsas/mv_sas.c +15 -13
@@ -1935,15 +1935,15 @@ static void mvs_work_queue(struct work_struct *work) struct delayed_work *dw = container_of(work, struct delayed_work, work); struct mvs_wq *mwq = container_of(dw, struct mvs_wq, work_q);struct mvs_info *mvi = mwq->mvi; -unsigned long flags; -spin_lock_irqsave (&mvi->lock, flags); -if (mwq->handler &PHY_PLUG_EVENT ) {u32 phy_no = (unsigned long ) mwq->data;struct sas_ha_struct *sas_ha = mvi->sas;struct mvs_phy *phy = &mvi->phy[phy_no];struct asd_sas_phy *sas_phy = &phy->sas_phy; +unsigned long flags; +spin_lock_irqsave (&mvi->lock, flags); +if (mwq->handler &PHY_PLUG_EVENT ) {if (phy->phy_event &PHY_PLUG_OUT ) {u32 tmp;struct sas_identify_frame *id;
@@ -1964,6 +1964,10 @@ static void mvs_work_queue(struct work_struct *work)mv_dprintk ("phy%d Attached Device\n" , phy_no); } } + }else if (mwq->handler &EXP_BRCT_CHG ) { + phy->phy_event &= ~EXP_BRCT_CHG ; + sas_ha->notify_port_event (sas_phy, +PORTE_BROADCAST_RCVD ); }list_del (&mwq->entry);spin_unlock_irqrestore (&mvi->lock, flags);
@@ -1982,7 +1986,7 @@ static int mvs_handle_event(struct mvs_info *mvi, void *data, int handler) mwq->handler = handler;MV_INIT_DELAYED_WORK (&mwq->work_q, mvs_work_queue, mwq);list_add_tail (&mwq->entry, &mvi->wq_list); -schedule_delayed_work (&mwq->work_q,HZ *2 ); +schedule_delayed_work (&mwq->work_q,HZ * io_delay); }else ret = -ENOMEM ;
@@ -2014,14 +2018,14 @@ static void mvs_sig_remove_timer(struct mvs_phy *phy)void mvs_int_port (struct mvs_info *mvi,int phy_no,u32 events) {u32 tmp; -struct sas_ha_struct *sas_ha = mvi->sas;struct mvs_phy *phy = &mvi->phy[phy_no];struct asd_sas_phy *sas_phy = &phy->sas_phy; phy->irq_status =MVS_CHIP_DISP ->read_port_irq_stat (mvi, phy_no); -mv_dprintk ("port %d ctrl sts=0x%X.\n" , phy_no+mvi->id*mvi->chip->n_phy, +MVS_CHIP_DISP ->write_port_irq_stat (mvi, phy_no, phy->irq_status); +mv_dprintk ("phy %d ctrl sts=%08X.\n" , phy_no+mvi->id*mvi->chip->n_phy,MVS_CHIP_DISP ->read_phy_ctl (mvi, phy_no)); -mv_dprintk ("Port %d irq sts = 0x%X\n" , phy_no+mvi->id*mvi->chip->n_phy, +mv_dprintk ("phy %d irq sts = %08X\n" , phy_no+mvi->id*mvi->chip->n_phy, phy->irq_status);/*
@@ -2096,13 +2100,11 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events) phy_no + mvi->id*mvi->chip->n_phy); } }else if (phy->irq_status &PHYEV_BROAD_CH ) { -mv_dprintk ("port %d broadcast change.\n" , - phy_no + mvi->id*mvi->chip->n_phy); -/* exception for Samsung disk drive*/ -mdelay (1000 ); - sas_ha->notify_port_event (sas_phy,PORTE_BROADCAST_RCVD ); +mv_dprintk ("phy %d broadcast change.\n" , + phy_no + mvi->id*mvi->chip->n_phy); +mvs_handle_event (mvi, (void *)(unsigned long )phy_no, +EXP_BRCT_CHG ); } -MVS_CHIP_DISP ->write_port_irq_stat (mvi, phy_no, phy->irq_status); }int mvs_int_rx (struct mvs_info *mvi,bool self_clear)
drivers/scsi/mvsas/mv_sas.h +2 -0
@@ -61,6 +61,7 @@#endif #define MV_MAX_U32 0xffffffff +extern int io_delay;extern struct mvs_tgt_initiator mvs_tgt;extern struct mvs_info *tgt_mvi;extern const struct mvs_dispatch mvs_64xx_dispatch;
@@ -93,6 +94,7 @@ extern const struct mvs_dispatch mvs_94xx_dispatch;enum dev_status {MVS_DEV_NORMAL =0x0 ,MVS_DEV_EH =0x1 , +MVS_DEV_OFF =0x2 , };
Signature · 1 line
1.6.2.2
Quoted 10 lines · Andy Yan
From
8b51aa63e8b123046a334d630ae045f479acbf6cMon Sep 17 00:00:00 2001
From: andy <[email protected]>
Date: Fri, 6 Nov 2009 17:03:21 +0800
Subject: [PATCH 2/7] Add supporting MSI featureMSI feature is implemented with mvsas driver.
Signed-off-by Andy <[email protected]>Signed-off-by Jacky <[email protected]>Signed-off-by Ke <[email protected]>
This doesn't compile:
CC [M] drivers/scsi/mvsas/mv_init.odrivers/scsi/mvsas/mv_init.c: In function ‘mvs_enable_msi’:drivers/scsi/mvsas/mv_init.c:197: error: ‘PCR_CMD’ undeclared (first use in this function) drivers/scsi/mvsas/mv_init.c:197: error: (Each undeclared identifier is reported only once drivers/scsi/mvsas/mv_init.c:197: error: for each function it appears in.) drivers/scsi/mvsas/mv_init.c:201: error: ‘PCR_MSI_CTRL’ undeclared (first use in this function) drivers/scsi/mvsas/mv_init.c: In function ‘mvs_disable_msi’:drivers/scsi/mvsas/mv_init.c:208: error: ‘PCR_CMD’ undeclared (first use in this function) drivers/scsi/mvsas/mv_init.c:212: error: ‘PCR_MSI_CTRL’ undeclared (first use in this function)
It looks like these definitions are added in patch 3 (after this one) ... you can't do that: a patch series has to be bisectable
James
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
drivers/scsi/mvsas/mv_init.c static void mvs_tasklet(unsigned long opaque) · line 199
Quoted 6 lines · Andy Yan
drivers/scsi/mvsas/mv_init.c +6
-0+void mvs_enable_msi (struct mvs_info *mvi) +{ +u32 tmp; +pci_read_config_dword (mvi->pdev,PCR_CMD , &tmp); + tmp |=1 <<10 ;/* disable interrupt */ +pci_write_config_dword (mvi->pdev,PCR_CMD , tmp);
What makes you think the pci_enable_msi() code doesn't set this bit?
drivers/scsi/mvsas/mv_init.c static void mvs_tasklet(unsigned long opaque) · line 203
Quoted 3 lines
drivers/scsi/mvsas/mv_init.c +3
-0+pci_read_config_dword (mvi->pdev,PCR_MSI_CTRL , &tmp); + tmp |=1 <<16 ;/* enable MSI */ +pci_write_config_dword (mvi->pdev,PCR_MSI_CTRL , tmp);
... and what makes you think it doesn't set this bit either?
drivers/scsi/mvsas/mv_init.c static struct pci_driver mvs_pci_driver = { · line 725
Quoted 7 lines
drivers/scsi/mvsas/mv_init.c +7
-0+static ssize_t +mvs_show_driver_version (struct device *cdev, +struct device_attribute *attr, +char *buffer) +{ +return snprintf (buffer,PAGE_SIZE ,"%s\n" ,DRV_VERSION ); +}
There's a lot of code in this patch not related to enabling MSI.
Signature · 4 lines
Matthew Wilcox Intel Open Source Technology Centre "Bill, look, we understand that you're interested in selling us this operating system, but compare it to ours. We can't possibly take such a retrograde step."