Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b5720729 authored by Hannes Reinecke's avatar Hannes Reinecke Committed by James Bottomley
Browse files

[SCSI] aic7xxx: Add suspend/resume support



The aic7xxx driver already contains fragments for suspend/resume
support. So we only need to update them to the current interface
and have full PCI suspend/resume.

Signed-off-by: default avatarHannes Reinecke <hare@suse.de>
Tested-by: default avatarJens Axboe <jens.axboe@oracle.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent eb7a1698
Loading
Loading
Loading
Loading
+0 −16
Original line number Original line Diff line number Diff line
@@ -60,8 +60,6 @@
#define	ID_OLV_274xD	0x04907783 /* Olivetti OEM (Differential) */
#define	ID_OLV_274xD	0x04907783 /* Olivetti OEM (Differential) */


static int aic7770_chip_init(struct ahc_softc *ahc);
static int aic7770_chip_init(struct ahc_softc *ahc);
static int aic7770_suspend(struct ahc_softc *ahc);
static int aic7770_resume(struct ahc_softc *ahc);
static int aha2840_load_seeprom(struct ahc_softc *ahc);
static int aha2840_load_seeprom(struct ahc_softc *ahc);
static ahc_device_setup_t ahc_aic7770_VL_setup;
static ahc_device_setup_t ahc_aic7770_VL_setup;
static ahc_device_setup_t ahc_aic7770_EISA_setup;
static ahc_device_setup_t ahc_aic7770_EISA_setup;
@@ -155,8 +153,6 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
		return (error);
		return (error);


	ahc->bus_chip_init = aic7770_chip_init;
	ahc->bus_chip_init = aic7770_chip_init;
	ahc->bus_suspend = aic7770_suspend;
	ahc->bus_resume = aic7770_resume;


	error = ahc_reset(ahc, /*reinit*/FALSE);
	error = ahc_reset(ahc, /*reinit*/FALSE);
	if (error != 0)
	if (error != 0)
@@ -272,18 +268,6 @@ aic7770_chip_init(struct ahc_softc *ahc)
	return (ahc_chip_init(ahc));
	return (ahc_chip_init(ahc));
}
}


static int
aic7770_suspend(struct ahc_softc *ahc)
{
	return (ahc_suspend(ahc));
}

static int
aic7770_resume(struct ahc_softc *ahc)
{
	return (ahc_resume(ahc));
}

/*
/*
 * Read the 284x SEEPROM.
 * Read the 284x SEEPROM.
 */
 */
+11 −0
Original line number Original line Diff line number Diff line
@@ -1003,8 +1003,15 @@ struct ahd_suspend_channel_state {
	uint8_t	seqctl;
	uint8_t	seqctl;
};
};


struct ahd_suspend_pci_state {
	uint32_t  devconfig;
	uint8_t   command;
	uint8_t   csize_lattime;
};

struct ahd_suspend_state {
struct ahd_suspend_state {
	struct	ahd_suspend_channel_state channel[2];
	struct	ahd_suspend_channel_state channel[2];
	struct  ahd_suspend_pci_state pci_state;
	uint8_t	optionmode;
	uint8_t	optionmode;
	uint8_t	dscommand0;
	uint8_t	dscommand0;
	uint8_t	dspcistatus;
	uint8_t	dspcistatus;
@@ -1333,6 +1340,8 @@ struct ahd_pci_identity *ahd_find_pci_device(ahd_dev_softc_t);
int			  ahd_pci_config(struct ahd_softc *,
int			  ahd_pci_config(struct ahd_softc *,
					 struct ahd_pci_identity *);
					 struct ahd_pci_identity *);
int	ahd_pci_test_register_access(struct ahd_softc *);
int	ahd_pci_test_register_access(struct ahd_softc *);
void	ahd_pci_suspend(struct ahd_softc *);
void	ahd_pci_resume(struct ahd_softc *);


/************************** SCB and SCB queue management **********************/
/************************** SCB and SCB queue management **********************/
void		ahd_qinfifo_requeue_tail(struct ahd_softc *ahd,
void		ahd_qinfifo_requeue_tail(struct ahd_softc *ahd,
@@ -1343,6 +1352,8 @@ struct ahd_softc *ahd_alloc(void *platform_arg, char *name);
int			 ahd_softc_init(struct ahd_softc *);
int			 ahd_softc_init(struct ahd_softc *);
void			 ahd_controller_info(struct ahd_softc *ahd, char *buf);
void			 ahd_controller_info(struct ahd_softc *ahd, char *buf);
int			 ahd_init(struct ahd_softc *ahd);
int			 ahd_init(struct ahd_softc *ahd);
int			 ahd_suspend(struct ahd_softc *ahd);
void			 ahd_resume(struct ahd_softc *ahd);
int			 ahd_default_config(struct ahd_softc *ahd);
int			 ahd_default_config(struct ahd_softc *ahd);
int			 ahd_parse_vpddata(struct ahd_softc *ahd,
int			 ahd_parse_vpddata(struct ahd_softc *ahd,
					   struct vpd_config *vpd);
					   struct vpd_config *vpd);
+1 −6
Original line number Original line Diff line number Diff line
@@ -7175,7 +7175,6 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd)
	ahd->flags &= ~AHD_ALL_INTERRUPTS;
	ahd->flags &= ~AHD_ALL_INTERRUPTS;
}
}


#if 0
int
int
ahd_suspend(struct ahd_softc *ahd)
ahd_suspend(struct ahd_softc *ahd)
{
{
@@ -7189,19 +7188,15 @@ ahd_suspend(struct ahd_softc *ahd)
	ahd_shutdown(ahd);
	ahd_shutdown(ahd);
	return (0);
	return (0);
}
}
#endif  /*  0  */


#if 0
void
int
ahd_resume(struct ahd_softc *ahd)
ahd_resume(struct ahd_softc *ahd)
{
{


	ahd_reset(ahd, /*reinit*/TRUE);
	ahd_reset(ahd, /*reinit*/TRUE);
	ahd_intr_enable(ahd, TRUE); 
	ahd_intr_enable(ahd, TRUE); 
	ahd_restart(ahd);
	ahd_restart(ahd);
	return (0);
}
}
#endif  /*  0  */


/************************** Busy Target Table *********************************/
/************************** Busy Target Table *********************************/
/*
/*
+50 −0
Original line number Original line Diff line number Diff line
@@ -50,6 +50,8 @@ static int ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd,
static int	ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd,
static int	ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd,
						 u_long *bus_addr,
						 u_long *bus_addr,
						 uint8_t __iomem **maddr);
						 uint8_t __iomem **maddr);
static int	ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg);
static int	ahd_linux_pci_dev_resume(struct pci_dev *pdev);
static void	ahd_linux_pci_dev_remove(struct pci_dev *pdev);
static void	ahd_linux_pci_dev_remove(struct pci_dev *pdev);


/* Define the macro locally since it's different for different class of chips.
/* Define the macro locally since it's different for different class of chips.
@@ -86,10 +88,58 @@ MODULE_DEVICE_TABLE(pci, ahd_linux_pci_id_table);
static struct pci_driver aic79xx_pci_driver = {
static struct pci_driver aic79xx_pci_driver = {
	.name		= "aic79xx",
	.name		= "aic79xx",
	.probe		= ahd_linux_pci_dev_probe,
	.probe		= ahd_linux_pci_dev_probe,
#ifdef CONFIG_PM
	.suspend	= ahd_linux_pci_dev_suspend,
	.resume		= ahd_linux_pci_dev_resume,
#endif
	.remove		= ahd_linux_pci_dev_remove,
	.remove		= ahd_linux_pci_dev_remove,
	.id_table	= ahd_linux_pci_id_table
	.id_table	= ahd_linux_pci_id_table
};
};


static int
ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg)
{
	struct ahd_softc *ahd = pci_get_drvdata(pdev);
	int rc;

	if ((rc = ahd_suspend(ahd)))
		return rc;

	ahd_pci_suspend(ahd);

	pci_save_state(pdev);
	pci_disable_device(pdev);

	if (mesg.event == PM_EVENT_SUSPEND)
		pci_set_power_state(pdev, PCI_D3hot);

	return rc;
}

static int
ahd_linux_pci_dev_resume(struct pci_dev *pdev)
{
	struct ahd_softc *ahd = pci_get_drvdata(pdev);
	int rc;

	pci_set_power_state(pdev, PCI_D0);
	pci_restore_state(pdev);

	if ((rc = pci_enable_device(pdev))) {
		dev_printk(KERN_ERR, &pdev->dev,
			   "failed to enable device after resume (%d)\n", rc);
		return rc;
	}

	pci_set_master(pdev);

	ahd_pci_resume(ahd);

	ahd_resume(ahd);

	return rc;
}

static void
static void
ahd_linux_pci_dev_remove(struct pci_dev *pdev)
ahd_linux_pci_dev_remove(struct pci_dev *pdev)
{
{
+27 −0
Original line number Original line Diff line number Diff line
@@ -389,6 +389,33 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
	return error;
	return error;
}
}


void
ahd_pci_suspend(struct ahd_softc *ahd)
{
	/*
	 * Save chip register configuration data for chip resets
	 * that occur during runtime and resume events.
	 */
	ahd->suspend_state.pci_state.devconfig =
	    ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4);
	ahd->suspend_state.pci_state.command =
	    ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/1);
	ahd->suspend_state.pci_state.csize_lattime =
	    ahd_pci_read_config(ahd->dev_softc, CSIZE_LATTIME, /*bytes*/1);

}

void
ahd_pci_resume(struct ahd_softc *ahd)
{
	ahd_pci_write_config(ahd->dev_softc, DEVCONFIG,
			     ahd->suspend_state.pci_state.devconfig, /*bytes*/4);
	ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
			     ahd->suspend_state.pci_state.command, /*bytes*/1);
	ahd_pci_write_config(ahd->dev_softc, CSIZE_LATTIME,
			     ahd->suspend_state.pci_state.csize_lattime, /*bytes*/1);
}

/*
/*
 * Perform some simple tests that should catch situations where
 * Perform some simple tests that should catch situations where
 * our registers are invalidly mapped.
 * our registers are invalidly mapped.
Loading