diff options
| author | Robert Hancock <hancockr@shaw.ca> | 2007-01-03 19:13:57 -0500 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2007-02-09 17:39:30 -0500 |
| commit | cdf56bcf14b9d441777703eef95eef807e4136ec (patch) | |
| tree | 9f5dcb34110b62e6ac46183b3ca9f24323cf62bc | |
| parent | 7102d230d6e8cf48ab366fa110c0a7f5ea160d07 (diff) | |
sata_nv: add suspend/resume support v3 (Resubmit)
Thoughts from Jeff & company on merging the patch below into libata-dev?
This has been in the -mm tree for over a month now, I haven't heard any
complaints about regressions..
Signed-off-by: Jeff Garzik <jeff@garzik.org>
| -rw-r--r-- | drivers/ata/sata_nv.c | 225 |
1 files changed, 161 insertions, 64 deletions
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index cbca983165d..246df22ecd0 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c | |||
| @@ -49,7 +49,7 @@ | |||
| 49 | #include <linux/libata.h> | 49 | #include <linux/libata.h> |
| 50 | 50 | ||
| 51 | #define DRV_NAME "sata_nv" | 51 | #define DRV_NAME "sata_nv" |
| 52 | #define DRV_VERSION "3.2" | 52 | #define DRV_VERSION "3.3" |
| 53 | 53 | ||
| 54 | #define NV_ADMA_DMA_BOUNDARY 0xffffffffUL | 54 | #define NV_ADMA_DMA_BOUNDARY 0xffffffffUL |
| 55 | 55 | ||
| @@ -213,12 +213,21 @@ struct nv_adma_port_priv { | |||
| 213 | dma_addr_t cpb_dma; | 213 | dma_addr_t cpb_dma; |
| 214 | struct nv_adma_prd *aprd; | 214 | struct nv_adma_prd *aprd; |
| 215 | dma_addr_t aprd_dma; | 215 | dma_addr_t aprd_dma; |
| 216 | void __iomem * ctl_block; | ||
| 217 | void __iomem * gen_block; | ||
| 218 | void __iomem * notifier_clear_block; | ||
| 216 | u8 flags; | 219 | u8 flags; |
| 217 | }; | 220 | }; |
| 218 | 221 | ||
| 222 | struct nv_host_priv { | ||
| 223 | unsigned long type; | ||
| 224 | }; | ||
| 225 | |||
| 219 | #define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT))))) | 226 | #define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT))))) |
| 220 | 227 | ||
| 221 | static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); | 228 | static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); |
| 229 | static void nv_remove_one (struct pci_dev *pdev); | ||
| 230 | static int nv_pci_device_resume(struct pci_dev *pdev); | ||
| 222 | static void nv_ck804_host_stop(struct ata_host *host); | 231 | static void nv_ck804_host_stop(struct ata_host *host); |
| 223 | static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance); | 232 | static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance); |
| 224 | static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance); | 233 | static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance); |
| @@ -239,6 +248,8 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance); | |||
| 239 | static void nv_adma_irq_clear(struct ata_port *ap); | 248 | static void nv_adma_irq_clear(struct ata_port *ap); |
| 240 | static int nv_adma_port_start(struct ata_port *ap); | 249 | static int nv_adma_port_start(struct ata_port *ap); |
| 241 | static void nv_adma_port_stop(struct ata_port *ap); | 250 | static void nv_adma_port_stop(struct ata_port *ap); |
| 251 | static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg); | ||
| 252 | static int nv_adma_port_resume(struct ata_port *ap); | ||
| 242 | static void nv_adma_error_handler(struct ata_port *ap); | 253 | static void nv_adma_error_handler(struct ata_port *ap); |
| 243 | static void nv_adma_host_stop(struct ata_host *host); | 254 | static void nv_adma_host_stop(struct ata_host *host); |
| 244 | static void nv_adma_bmdma_setup(struct ata_queued_cmd *qc); | 255 | static void nv_adma_bmdma_setup(struct ata_queued_cmd *qc); |
| @@ -284,7 +295,9 @@ static struct pci_driver nv_pci_driver = { | |||
| 284 | .name = DRV_NAME, | 295 | .name = DRV_NAME, |
| 285 | .id_table = nv_pci_tbl, | 296 | .id_table = nv_pci_tbl, |
| 286 | .probe = nv_init_one, | 297 | .probe = nv_init_one, |
| 287 | .remove = ata_pci_remove_one, | 298 | .suspend = ata_pci_device_suspend, |
| 299 | .resume = nv_pci_device_resume, | ||
| 300 | .remove = nv_remove_one, | ||
| 288 | }; | 301 | }; |
| 289 | 302 | ||
| 290 | static struct scsi_host_template nv_sht = { | 303 | static struct scsi_host_template nv_sht = { |
| @@ -303,6 +316,8 @@ static struct scsi_host_template nv_sht = { | |||
| 303 | .slave_configure = ata_scsi_slave_config, | 316 | .slave_configure = ata_scsi_slave_config, |
| 304 | .slave_destroy = ata_scsi_slave_destroy, | 317 | .slave_destroy = ata_scsi_slave_destroy, |
| 305 | .bios_param = ata_std_bios_param, | 318 | .bios_param = ata_std_bios_param, |
| 319 | .suspend = ata_scsi_device_suspend, | ||
| 320 | .resume = ata_scsi_device_resume, | ||
| 306 | }; | 321 | }; |
| 307 | 322 | ||
| 308 | static struct scsi_host_template nv_adma_sht = { | 323 | static struct scsi_host_template nv_adma_sht = { |
| @@ -321,6 +336,8 @@ static struct scsi_host_template nv_adma_sht = { | |||
| 321 | .slave_configure = nv_adma_slave_config, | 336 | .slave_configure = nv_adma_slave_config, |
| 322 | .slave_destroy = ata_scsi_slave_destroy, | 337 | .slave_destroy = ata_scsi_slave_destroy, |
| 323 | .bios_param = ata_std_bios_param, | 338 | .bios_param = ata_std_bios_param, |
| 339 | .suspend = ata_scsi_device_suspend, | ||
| 340 | .resume = ata_scsi_device_resume, | ||
| 324 | }; | 341 | }; |
| 325 | 342 | ||
| 326 | static const struct ata_port_operations nv_generic_ops = { | 343 | static const struct ata_port_operations nv_generic_ops = { |
| @@ -429,6 +446,8 @@ static const struct ata_port_operations nv_adma_ops = { | |||
| 429 | .scr_write = nv_scr_write, | 446 | .scr_write = nv_scr_write, |
| 430 | .port_start = nv_adma_port_start, | 447 | .port_start = nv_adma_port_start, |
| 431 | .port_stop = nv_adma_port_stop, | 448 | .port_stop = nv_adma_port_stop, |
| 449 | .port_suspend = nv_adma_port_suspend, | ||
| 450 | .port_resume = nv_adma_port_resume, | ||
| 432 | .host_stop = nv_adma_host_stop, | 451 | .host_stop = nv_adma_host_stop, |
| 433 | }; | 452 | }; |
| 434 | 453 | ||
| @@ -467,6 +486,7 @@ static struct ata_port_info nv_port_info[] = { | |||
| 467 | { | 486 | { |
| 468 | .sht = &nv_adma_sht, | 487 | .sht = &nv_adma_sht, |
| 469 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | 488 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
| 489 | ATA_FLAG_HRST_TO_RESUME | | ||
| 470 | ATA_FLAG_MMIO | ATA_FLAG_NCQ, | 490 | ATA_FLAG_MMIO | ATA_FLAG_NCQ, |
| 471 | .pio_mask = NV_PIO_MASK, | 491 | .pio_mask = NV_PIO_MASK, |
| 472 | .mwdma_mask = NV_MWDMA_MASK, | 492 | .mwdma_mask = NV_MWDMA_MASK, |
| @@ -483,32 +503,10 @@ MODULE_VERSION(DRV_VERSION); | |||
| 483 | 503 | ||
| 484 | static int adma_enabled = 1; | 504 | static int adma_enabled = 1; |
| 485 | 505 | ||
| 486 | static inline void __iomem *__nv_adma_ctl_block(void __iomem *mmio, | ||
| 487 | unsigned int port_no) | ||
| 488 | { | ||
| 489 | mmio += NV_ADMA_PORT + port_no * NV_ADMA_PORT_SIZE; | ||
| 490 | return mmio; | ||
| 491 | } | ||
| 492 | |||
| 493 | static inline void __iomem *nv_adma_ctl_block(struct ata_port *ap) | ||
| 494 | { | ||
| 495 | return __nv_adma_ctl_block(ap->host->mmio_base, ap->port_no); | ||
| 496 | } | ||
| 497 | |||
| 498 | static inline void __iomem *nv_adma_gen_block(struct ata_port *ap) | ||
| 499 | { | ||
| 500 | return (ap->host->mmio_base + NV_ADMA_GEN); | ||
| 501 | } | ||
| 502 | |||
| 503 | static inline void __iomem *nv_adma_notifier_clear_block(struct ata_port *ap) | ||
| 504 | { | ||
| 505 | return (nv_adma_gen_block(ap) + NV_ADMA_NOTIFIER_CLEAR + (4 * ap->port_no)); | ||
| 506 | } | ||
| 507 | |||
| 508 | static void nv_adma_register_mode(struct ata_port *ap) | 506 | static void nv_adma_register_mode(struct ata_port *ap) |
| 509 | { | 507 | { |
| 510 | void __iomem *mmio = nv_adma_ctl_block(ap); | ||
| 511 | struct nv_adma_port_priv *pp = ap->private_data; | 508 | struct nv_adma_port_priv *pp = ap->private_data; |
| 509 | void __iomem *mmio = pp->ctl_block; | ||
| 512 | u16 tmp; | 510 | u16 tmp; |
| 513 | 511 | ||
| 514 | if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) | 512 | if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) |
| @@ -522,8 +520,8 @@ static void nv_adma_register_mode(struct ata_port *ap) | |||
| 522 | 520 | ||
| 523 | static void nv_adma_mode(struct ata_port *ap) | 521 | static void nv_adma_mode(struct ata_port *ap) |
| 524 | { | 522 | { |
| 525 | void __iomem *mmio = nv_adma_ctl_block(ap); | ||
| 526 | struct nv_adma_port_priv *pp = ap->private_data; | 523 | struct nv_adma_port_priv *pp = ap->private_data; |
| 524 | void __iomem *mmio = pp->ctl_block; | ||
| 527 | u16 tmp; | 525 | u16 tmp; |
| 528 | 526 | ||
| 529 | if (!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) | 527 | if (!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) |
| @@ -684,7 +682,7 @@ static void nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err) | |||
| 684 | For NCQ commands the current status may have nothing to do with | 682 | For NCQ commands the current status may have nothing to do with |
| 685 | the command just completed. */ | 683 | the command just completed. */ |
| 686 | if(qc->tf.protocol != ATA_PROT_NCQ) | 684 | if(qc->tf.protocol != ATA_PROT_NCQ) |
| 687 | ata_status = readb(nv_adma_ctl_block(ap) + (ATA_REG_STATUS * 4)); | 685 | ata_status = readb(pp->ctl_block + (ATA_REG_STATUS * 4)); |
| 688 | 686 | ||
| 689 | if(have_err || force_err) | 687 | if(have_err || force_err) |
| 690 | ata_status |= ATA_ERR; | 688 | ata_status |= ATA_ERR; |
| @@ -735,7 +733,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) | |||
| 735 | 733 | ||
| 736 | if (ap && !(ap->flags & ATA_FLAG_DISABLED)) { | 734 | if (ap && !(ap->flags & ATA_FLAG_DISABLED)) { |
| 737 | struct nv_adma_port_priv *pp = ap->private_data; | 735 | struct nv_adma_port_priv *pp = ap->private_data; |
| 738 | void __iomem *mmio = nv_adma_ctl_block(ap); | 736 | void __iomem *mmio = pp->ctl_block; |
| 739 | u16 status; | 737 | u16 status; |
| 740 | u32 gen_ctl; | 738 | u32 gen_ctl; |
| 741 | int have_global_err = 0; | 739 | int have_global_err = 0; |
| @@ -758,7 +756,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) | |||
| 758 | notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); | 756 | notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); |
| 759 | notifier_clears[i] = notifier | notifier_error; | 757 | notifier_clears[i] = notifier | notifier_error; |
| 760 | 758 | ||
| 761 | gen_ctl = readl(nv_adma_gen_block(ap) + NV_ADMA_GEN_CTL); | 759 | gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL); |
| 762 | 760 | ||
| 763 | if( !NV_ADMA_CHECK_INTR(gen_ctl, ap->port_no) && !notifier && | 761 | if( !NV_ADMA_CHECK_INTR(gen_ctl, ap->port_no) && !notifier && |
| 764 | !notifier_error) | 762 | !notifier_error) |
| @@ -816,10 +814,10 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) | |||
| 816 | if(notifier_clears[0] || notifier_clears[1]) { | 814 | if(notifier_clears[0] || notifier_clears[1]) { |
| 817 | /* Note: Both notifier clear registers must be written | 815 | /* Note: Both notifier clear registers must be written |
| 818 | if either is set, even if one is zero, according to NVIDIA. */ | 816 | if either is set, even if one is zero, according to NVIDIA. */ |
| 819 | writel(notifier_clears[0], | 817 | struct nv_adma_port_priv *pp = host->ports[0]->private_data; |
| 820 | nv_adma_notifier_clear_block(host->ports[0])); | 818 | writel(notifier_clears[0], pp->notifier_clear_block); |
| 821 | writel(notifier_clears[1], | 819 | pp = host->ports[1]->private_data; |
| 822 | nv_adma_notifier_clear_block(host->ports[1])); | 820 | writel(notifier_clears[1], pp->notifier_clear_block); |
| 823 | } | 821 | } |
| 824 | 822 | ||
| 825 | spin_unlock(&host->lock); | 823 | spin_unlock(&host->lock); |
| @@ -829,7 +827,8 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) | |||
| 829 | 827 | ||
| 830 | static void nv_adma_irq_clear(struct ata_port *ap) | 828 | static void nv_adma_irq_clear(struct ata_port *ap) |
| 831 | { | 829 | { |
| 832 | void __iomem *mmio = nv_adma_ctl_block(ap); | 830 | struct nv_adma_port_priv *pp = ap->private_data; |
| 831 | void __iomem *mmio = pp->ctl_block; | ||
| 833 | u16 status = readw(mmio + NV_ADMA_STAT); | 832 | u16 status = readw(mmio + NV_ADMA_STAT); |
| 834 | u32 notifier = readl(mmio + NV_ADMA_NOTIFIER); | 833 | u32 notifier = readl(mmio + NV_ADMA_NOTIFIER); |
| 835 | u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); | 834 | u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); |
| @@ -838,7 +837,7 @@ static void nv_adma_irq_clear(struct ata_port *ap) | |||
| 838 | /* clear ADMA status */ | 837 | /* clear ADMA status */ |
| 839 | writew(status, mmio + NV_ADMA_STAT); | 838 | writew(status, mmio + NV_ADMA_STAT); |
| 840 | writel(notifier | notifier_error, | 839 | writel(notifier | notifier_error, |
| 841 | nv_adma_notifier_clear_block(ap)); | 840 | pp->notifier_clear_block); |
| 842 | 841 | ||
| 843 | /** clear legacy status */ | 842 | /** clear legacy status */ |
| 844 | outb(inb(dma_stat_addr), dma_stat_addr); | 843 | outb(inb(dma_stat_addr), dma_stat_addr); |
| @@ -920,7 +919,7 @@ static int nv_adma_port_start(struct ata_port *ap) | |||
| 920 | int rc; | 919 | int rc; |
| 921 | void *mem; | 920 | void *mem; |
| 922 | dma_addr_t mem_dma; | 921 | dma_addr_t mem_dma; |
| 923 | void __iomem *mmio = nv_adma_ctl_block(ap); | 922 | void __iomem *mmio; |
| 924 | u16 tmp; | 923 | u16 tmp; |
| 925 | 924 | ||
| 926 | VPRINTK("ENTER\n"); | 925 | VPRINTK("ENTER\n"); |
| @@ -935,6 +934,13 @@ static int nv_adma_port_start(struct ata_port *ap) | |||
| 935 | goto err_out; | 934 | goto err_out; |
| 936 | } | 935 | } |
| 937 | 936 | ||
| 937 | mmio = ap->host->mmio_base + NV_ADMA_PORT + | ||
| 938 | ap->port_no * NV_ADMA_PORT_SIZE; | ||
| 939 | pp->ctl_block = mmio; | ||
| 940 | pp->gen_block = ap->host->mmio_base + NV_ADMA_GEN; | ||
| 941 | pp->notifier_clear_block = pp->gen_block + | ||
| 942 | NV_ADMA_NOTIFIER_CLEAR + (4 * ap->port_no); | ||
| 943 | |||
| 938 | mem = dma_alloc_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ, | 944 | mem = dma_alloc_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ, |
| 939 | &mem_dma, GFP_KERNEL); | 945 | &mem_dma, GFP_KERNEL); |
| 940 | 946 | ||
| @@ -975,9 +981,9 @@ static int nv_adma_port_start(struct ata_port *ap) | |||
| 975 | /* clear CPB fetch count */ | 981 | /* clear CPB fetch count */ |
| 976 | writew(0, mmio + NV_ADMA_CPB_COUNT); | 982 | writew(0, mmio + NV_ADMA_CPB_COUNT); |
| 977 | 983 | ||
| 978 | /* clear GO for register mode */ | 984 | /* clear GO for register mode, enable interrupt */ |
| 979 | tmp = readw(mmio + NV_ADMA_CTL); | 985 | tmp = readw(mmio + NV_ADMA_CTL); |
| 980 | writew(tmp & ~NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL); | 986 | writew( (tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL); |
| 981 | 987 | ||
| 982 | tmp = readw(mmio + NV_ADMA_CTL); | 988 | tmp = readw(mmio + NV_ADMA_CTL); |
| 983 | writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); | 989 | writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); |
| @@ -999,7 +1005,7 @@ static void nv_adma_port_stop(struct ata_port *ap) | |||
| 999 | { | 1005 | { |
| 1000 | struct device *dev = ap->host->dev; | 1006 | struct device *dev = ap->host->dev; |
| 1001 | struct nv_adma_port_priv *pp = ap->private_data; | 1007 | struct nv_adma_port_priv *pp = ap->private_data; |
| 1002 | void __iomem *mmio = nv_adma_ctl_block(ap); | 1008 | void __iomem *mmio = pp->ctl_block; |
| 1003 | 1009 | ||
| 1004 | VPRINTK("ENTER\n"); | 1010 | VPRINTK("ENTER\n"); |
| 1005 | 1011 | ||
| @@ -1011,6 +1017,55 @@ static void nv_adma_port_stop(struct ata_port *ap) | |||
| 1011 | ata_port_stop(ap); | 1017 | ata_port_stop(ap); |
| 1012 | } | 1018 | } |
| 1013 | 1019 | ||
| 1020 | static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg) | ||
| 1021 | { | ||
| 1022 | struct nv_adma_port_priv *pp = ap->private_data; | ||
| 1023 | void __iomem *mmio = pp->ctl_block; | ||
| 1024 | |||
| 1025 | /* Go to register mode - clears GO */ | ||
| 1026 | nv_adma_register_mode(ap); | ||
| 1027 | |||
| 1028 | /* clear CPB fetch count */ | ||
| 1029 | writew(0, mmio + NV_ADMA_CPB_COUNT); | ||
| 1030 | |||
| 1031 | /* disable interrupt, shut down port */ | ||
| 1032 | writew(0, mmio + NV_ADMA_CTL); | ||
| 1033 | |||
| 1034 | return 0; | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | static int nv_adma_port_resume(struct ata_port *ap) | ||
| 1038 | { | ||
| 1039 | struct nv_adma_port_priv *pp = ap->private_data; | ||
| 1040 | void __iomem *mmio = pp->ctl_block; | ||
| 1041 | u16 tmp; | ||
| 1042 | |||
| 1043 | /* set CPB block location */ | ||
| 1044 | writel(pp->cpb_dma & 0xFFFFFFFF, mmio + NV_ADMA_CPB_BASE_LOW); | ||
| 1045 | writel((pp->cpb_dma >> 16 ) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH); | ||
| 1046 | |||
| 1047 | /* clear any outstanding interrupt conditions */ | ||
| 1048 | writew(0xffff, mmio + NV_ADMA_STAT); | ||
| 1049 | |||
| 1050 | /* initialize port variables */ | ||
| 1051 | pp->flags |= NV_ADMA_PORT_REGISTER_MODE; | ||
| 1052 | |||
| 1053 | /* clear CPB fetch count */ | ||
| 1054 | writew(0, mmio + NV_ADMA_CPB_COUNT); | ||
| 1055 | |||
| 1056 | /* clear GO for register mode, enable interrupt */ | ||
| 1057 | tmp = readw(mmio + NV_ADMA_CTL); | ||
| 1058 | writew((tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL); | ||
| 1059 | |||
| 1060 | tmp = readw(mmio + NV_ADMA_CTL); | ||
| 1061 | writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); | ||
| 1062 | readl( mmio + NV_ADMA_CTL ); /* flush posted write */ | ||
| 1063 | udelay(1); | ||
| 1064 | writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); | ||
| 1065 | readl( mmio + NV_ADMA_CTL ); /* flush posted write */ | ||
| 1066 | |||
| 1067 | return 0; | ||
| 1068 | } | ||
| 1014 | 1069 | ||
| 1015 | static void nv_adma_setup_port(struct ata_probe_ent *probe_ent, unsigned int port) | 1070 | static void nv_adma_setup_port(struct ata_probe_ent *probe_ent, unsigned int port) |
| 1016 | { | 1071 | { |
| @@ -1056,15 +1111,6 @@ static int nv_adma_host_init(struct ata_probe_ent *probe_ent) | |||
| 1056 | for (i = 0; i < probe_ent->n_ports; i++) | 1111 | for (i = 0; i < probe_ent->n_ports; i++) |
| 1057 | nv_adma_setup_port(probe_ent, i); | 1112 | nv_adma_setup_port(probe_ent, i); |
| 1058 | 1113 | ||
| 1059 | for (i = 0; i < probe_ent->n_ports; i++) { | ||
| 1060 | void __iomem *mmio = __nv_adma_ctl_block(probe_ent->mmio_base, i); | ||
| 1061 | u16 tmp; | ||
| 1062 | |||
| 1063 | /* enable interrupt, clear reset if not already clear */ | ||
| 1064 | tmp = readw(mmio + NV_ADMA_CTL); | ||
| 1065 | writew(tmp | NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL); | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | return 0; | 1114 | return 0; |
| 1069 | } | 1115 | } |
| 1070 | 1116 | ||
| @@ -1118,8 +1164,6 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc) | |||
| 1118 | NV_CPB_CTL_APRD_VALID | | 1164 | NV_CPB_CTL_APRD_VALID | |
| 1119 | NV_CPB_CTL_IEN; | 1165 | NV_CPB_CTL_IEN; |
| 1120 | 1166 | ||
| 1121 | VPRINTK("qc->flags = 0x%lx\n", qc->flags); | ||
| 1122 | |||
| 1123 | if (!(qc->flags & ATA_QCFLAG_DMAMAP) || | 1167 | if (!(qc->flags & ATA_QCFLAG_DMAMAP) || |
| 1124 | (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) { | 1168 | (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) { |
| 1125 | nv_adma_register_mode(qc->ap); | 1169 | nv_adma_register_mode(qc->ap); |
| @@ -1137,6 +1181,8 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc) | |||
| 1137 | if (qc->tf.protocol == ATA_PROT_NCQ) | 1181 | if (qc->tf.protocol == ATA_PROT_NCQ) |
| 1138 | ctl_flags |= NV_CPB_CTL_QUEUE | NV_CPB_CTL_FPDMA; | 1182 | ctl_flags |= NV_CPB_CTL_QUEUE | NV_CPB_CTL_FPDMA; |
| 1139 | 1183 | ||
| 1184 | VPRINTK("qc->flags = 0x%lx\n", qc->flags); | ||
| 1185 | |||
| 1140 | nv_adma_tf_to_cpb(&qc->tf, cpb->tf); | 1186 | nv_adma_tf_to_cpb(&qc->tf, cpb->tf); |
| 1141 | 1187 | ||
| 1142 | nv_adma_fill_sg(qc, cpb); | 1188 | nv_adma_fill_sg(qc, cpb); |
| @@ -1150,7 +1196,7 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc) | |||
| 1150 | static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc) | 1196 | static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc) |
| 1151 | { | 1197 | { |
| 1152 | struct nv_adma_port_priv *pp = qc->ap->private_data; | 1198 | struct nv_adma_port_priv *pp = qc->ap->private_data; |
| 1153 | void __iomem *mmio = nv_adma_ctl_block(qc->ap); | 1199 | void __iomem *mmio = pp->ctl_block; |
| 1154 | 1200 | ||
| 1155 | VPRINTK("ENTER\n"); | 1201 | VPRINTK("ENTER\n"); |
| 1156 | 1202 | ||
| @@ -1335,13 +1381,13 @@ static void nv_adma_error_handler(struct ata_port *ap) | |||
| 1335 | { | 1381 | { |
| 1336 | struct nv_adma_port_priv *pp = ap->private_data; | 1382 | struct nv_adma_port_priv *pp = ap->private_data; |
| 1337 | if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) { | 1383 | if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) { |
| 1338 | void __iomem *mmio = nv_adma_ctl_block(ap); | 1384 | void __iomem *mmio = pp->ctl_block; |
| 1339 | int i; | 1385 | int i; |
| 1340 | u16 tmp; | 1386 | u16 tmp; |
| 1341 | 1387 | ||
| 1342 | u32 notifier = readl(mmio + NV_ADMA_NOTIFIER); | 1388 | u32 notifier = readl(mmio + NV_ADMA_NOTIFIER); |
| 1343 | u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); | 1389 | u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); |
| 1344 | u32 gen_ctl = readl(nv_adma_gen_block(ap) + NV_ADMA_GEN_CTL); | 1390 | u32 gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL); |
| 1345 | u32 status = readw(mmio + NV_ADMA_STAT); | 1391 | u32 status = readw(mmio + NV_ADMA_STAT); |
| 1346 | 1392 | ||
| 1347 | ata_port_printk(ap, KERN_ERR, "EH in ADMA mode, notifier 0x%X " | 1393 | ata_port_printk(ap, KERN_ERR, "EH in ADMA mode, notifier 0x%X " |
| @@ -1386,6 +1432,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 1386 | static int printed_version = 0; | 1432 | static int printed_version = 0; |
| 1387 | struct ata_port_info *ppi[2]; | 1433 | struct ata_port_info *ppi[2]; |
| 1388 | struct ata_probe_ent *probe_ent; | 1434 | struct ata_probe_ent *probe_ent; |
| 1435 | struct nv_host_priv *hpriv; | ||
| 1389 | int pci_dev_busy = 0; | 1436 | int pci_dev_busy = 0; |
| 1390 | int rc; | 1437 | int rc; |
| 1391 | u32 bar; | 1438 | u32 bar; |
| @@ -1400,7 +1447,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 1400 | if (pci_resource_start(pdev, bar) == 0) | 1447 | if (pci_resource_start(pdev, bar) == 0) |
| 1401 | return -ENODEV; | 1448 | return -ENODEV; |
| 1402 | 1449 | ||
| 1403 | if ( !printed_version++) | 1450 | if (!printed_version++) |
| 1404 | dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); | 1451 | dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); |
| 1405 | 1452 | ||
| 1406 | rc = pci_enable_device(pdev); | 1453 | rc = pci_enable_device(pdev); |
| @@ -1432,6 +1479,10 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 1432 | 1479 | ||
| 1433 | rc = -ENOMEM; | 1480 | rc = -ENOMEM; |
| 1434 | 1481 | ||
| 1482 | hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL); | ||
| 1483 | if (!hpriv) | ||
| 1484 | goto err_out_regions; | ||
| 1485 | |||
| 1435 | ppi[0] = ppi[1] = &nv_port_info[type]; | 1486 | ppi[0] = ppi[1] = &nv_port_info[type]; |
| 1436 | probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); | 1487 | probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); |
| 1437 | if (!probe_ent) | 1488 | if (!probe_ent) |
| @@ -1442,6 +1493,8 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 1442 | rc = -EIO; | 1493 | rc = -EIO; |
| 1443 | goto err_out_free_ent; | 1494 | goto err_out_free_ent; |
| 1444 | } | 1495 | } |
| 1496 | probe_ent->private_data = hpriv; | ||
| 1497 | hpriv->type = type; | ||
| 1445 | 1498 | ||
| 1446 | base = (unsigned long)probe_ent->mmio_base; | 1499 | base = (unsigned long)probe_ent->mmio_base; |
| 1447 | 1500 | ||
| @@ -1486,6 +1539,60 @@ err_out: | |||
| 1486 | return rc; | 1539 | return rc; |
| 1487 | } | 1540 | } |
| 1488 | 1541 | ||
| 1542 | static void nv_remove_one (struct pci_dev *pdev) | ||
| 1543 | { | ||
| 1544 | struct ata_host *host = dev_get_drvdata(&pdev->dev); | ||
| 1545 | struct nv_host_priv *hpriv = host->private_data; | ||
| 1546 | |||
| 1547 | ata_pci_remove_one(pdev); | ||
| 1548 | kfree(hpriv); | ||
| 1549 | } | ||
| 1550 | |||
| 1551 | static int nv_pci_device_resume(struct pci_dev *pdev) | ||
| 1552 | { | ||
| 1553 | struct ata_host *host = dev_get_drvdata(&pdev->dev); | ||
| 1554 | struct nv_host_priv *hpriv = host->private_data; | ||
| 1555 | |||
| 1556 | ata_pci_device_do_resume(pdev); | ||
| 1557 | |||
| 1558 | if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { | ||
| 1559 | if(hpriv->type >= CK804) { | ||
| 1560 | u8 regval; | ||
| 1561 | |||
| 1562 | pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); | ||
| 1563 | regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN; | ||
| 1564 | pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); | ||
| 1565 | } | ||
| 1566 | if(hpriv->type == ADMA) { | ||
| 1567 | u32 tmp32; | ||
| 1568 | struct nv_adma_port_priv *pp; | ||
| 1569 | /* enable/disable ADMA on the ports appropriately */ | ||
| 1570 | pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32); | ||
| 1571 | |||
| 1572 | pp = host->ports[0]->private_data; | ||
| 1573 | if(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) | ||
| 1574 | tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN | | ||
| 1575 | NV_MCP_SATA_CFG_20_PORT0_PWB_EN); | ||
| 1576 | else | ||
| 1577 | tmp32 |= (NV_MCP_SATA_CFG_20_PORT0_EN | | ||
| 1578 | NV_MCP_SATA_CFG_20_PORT0_PWB_EN); | ||
| 1579 | pp = host->ports[1]->private_data; | ||
| 1580 | if(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) | ||
| 1581 | tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT1_EN | | ||
| 1582 | NV_MCP_SATA_CFG_20_PORT1_PWB_EN); | ||
| 1583 | else | ||
| 1584 | tmp32 |= (NV_MCP_SATA_CFG_20_PORT1_EN | | ||
| 1585 | NV_MCP_SATA_CFG_20_PORT1_PWB_EN); | ||
| 1586 | |||
| 1587 | pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32); | ||
| 1588 | } | ||
| 1589 | } | ||
| 1590 | |||
| 1591 | ata_host_resume(host); | ||
| 1592 | |||
| 1593 | return 0; | ||
| 1594 | } | ||
| 1595 | |||
| 1489 | static void nv_ck804_host_stop(struct ata_host *host) | 1596 | static void nv_ck804_host_stop(struct ata_host *host) |
| 1490 | { | 1597 | { |
| 1491 | struct pci_dev *pdev = to_pci_dev(host->dev); | 1598 | struct pci_dev *pdev = to_pci_dev(host->dev); |
| @@ -1502,18 +1609,8 @@ static void nv_ck804_host_stop(struct ata_host *host) | |||
| 1502 | static void nv_adma_host_stop(struct ata_host *host) | 1609 | static void nv_adma_host_stop(struct ata_host *host) |
| 1503 | { | 1610 | { |
| 1504 | struct pci_dev *pdev = to_pci_dev(host->dev); | 1611 | struct pci_dev *pdev = to_pci_dev(host->dev); |
| 1505 | int i; | ||
| 1506 | u32 tmp32; | 1612 | u32 tmp32; |
| 1507 | 1613 | ||
| 1508 | for (i = 0; i < host->n_ports; i++) { | ||
| 1509 | void __iomem *mmio = __nv_adma_ctl_block(host->mmio_base, i); | ||
| 1510 | u16 tmp; | ||
| 1511 | |||
| 1512 | /* disable interrupt */ | ||
| 1513 | tmp = readw(mmio + NV_ADMA_CTL); | ||
| 1514 | writew(tmp & ~NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL); | ||
| 1515 | } | ||
| 1516 | |||
| 1517 | /* disable ADMA on the ports */ | 1614 | /* disable ADMA on the ports */ |
| 1518 | pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32); | 1615 | pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32); |
| 1519 | tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN | | 1616 | tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN | |
