/* * PMC-Sierra PM8001/8081/8088/8089 SAS/SATA based host adapters driver * * Copyright (c) 2008-2009 USI Co., Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce at minimum a disclaimer * substantially similar to the "NO WARRANTY" disclaimer below * ("Disclaimer") and any redistribution must be conditioned upon * including a substantially similar Disclaimer requirement for further * binary redistribution. * 3. Neither the names of the above-listed copyright holders nor the names * of any contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL") version 2 as published by the Free * Software Foundation. * * NO WARRANTY * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * */ #include <linux/slab.h> #include "pm8001_sas.h" #include "pm8001_chips.h" #include "pm80xx_hwi.h" static ulong logging_level = …; module_param(logging_level, ulong, 0644); MODULE_PARM_DESC(…) …; static ulong link_rate = …; module_param(link_rate, ulong, 0644); MODULE_PARM_DESC(…) …; bool pm8001_use_msix = …; module_param_named(use_msix, pm8001_use_msix, bool, 0444); MODULE_PARM_DESC(…) …; static bool pm8001_use_tasklet = …; module_param_named(use_tasklet, pm8001_use_tasklet, bool, 0444); MODULE_PARM_DESC(…) …; static bool pm8001_read_wwn = …; module_param_named(read_wwn, pm8001_read_wwn, bool, 0444); MODULE_PARM_DESC(…) …; static struct scsi_transport_template *pm8001_stt; static int pm8001_init_ccb_tag(struct pm8001_hba_info *); /* * chip info structure to identify chip key functionality as * encryption available/not, no of ports, hw specific function ref */ static const struct pm8001_chip_info pm8001_chips[] = …; static int pm8001_id; LIST_HEAD(…); struct workqueue_struct *pm8001_wq; static void pm8001_map_queues(struct Scsi_Host *shost) { … } /* * The main structure which LLDD must register for scsi core. */ static const struct scsi_host_template pm8001_sht = …; /* * Sas layer call this function to execute specific task. */ static struct sas_domain_function_template pm8001_transport_ops = …; /** * pm8001_phy_init - initiate our adapter phys * @pm8001_ha: our hba structure. * @phy_id: phy id. */ static void pm8001_phy_init(struct pm8001_hba_info *pm8001_ha, int phy_id) { … } /** * pm8001_free - free hba * @pm8001_ha: our hba structure. */ static void pm8001_free(struct pm8001_hba_info *pm8001_ha) { … } /** * pm8001_tasklet() - tasklet for 64 msi-x interrupt handler * @opaque: the passed general host adapter struct * Note: pm8001_tasklet is common for pm8001 & pm80xx */ static void pm8001_tasklet(unsigned long opaque) { … } static void pm8001_init_tasklet(struct pm8001_hba_info *pm8001_ha) { … } static void pm8001_kill_tasklet(struct pm8001_hba_info *pm8001_ha) { … } static irqreturn_t pm8001_handle_irq(struct pm8001_hba_info *pm8001_ha, int irq) { … } /** * pm8001_interrupt_handler_msix - main MSIX interrupt handler. * It obtains the vector number and calls the equivalent bottom * half or services directly. * @irq: interrupt number * @opaque: the passed outbound queue/vector. Host structure is * retrieved from the same. */ static irqreturn_t pm8001_interrupt_handler_msix(int irq, void *opaque) { … } /** * pm8001_interrupt_handler_intx - main INTx interrupt handler. * @irq: interrupt number * @dev_id: sas_ha structure. The HBA is retrieved from sas_ha structure. */ static irqreturn_t pm8001_interrupt_handler_intx(int irq, void *dev_id) { … } static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha); static void pm8001_free_irq(struct pm8001_hba_info *pm8001_ha); /** * pm8001_alloc - initiate our hba structure and 6 DMAs area. * @pm8001_ha: our hba structure. * @ent: PCI device ID structure to match on */ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, const struct pci_device_id *ent) { … } /** * pm8001_ioremap - remap the pci high physical address to kernel virtual * address so that we can access them. * @pm8001_ha: our hba structure. */ static int pm8001_ioremap(struct pm8001_hba_info *pm8001_ha) { … } /** * pm8001_pci_alloc - initialize our ha card structure * @pdev: pci device. * @ent: ent * @shost: scsi host struct which has been initialized before. */ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev, const struct pci_device_id *ent, struct Scsi_Host *shost) { … } /** * pci_go_44 - pm8001 specified, its DMA is 44 bit rather than 64 bit * @pdev: pci device. */ static int pci_go_44(struct pci_dev *pdev) { … } /** * pm8001_prep_sas_ha_init - allocate memory in general hba struct && init them. * @shost: scsi host which has been allocated outside. * @chip_info: our ha struct. */ static int pm8001_prep_sas_ha_init(struct Scsi_Host *shost, const struct pm8001_chip_info *chip_info) { … } /** * pm8001_post_sas_ha_init - initialize general hba struct defined in libsas * @shost: scsi host which has been allocated outside * @chip_info: our ha struct. */ static void pm8001_post_sas_ha_init(struct Scsi_Host *shost, const struct pm8001_chip_info *chip_info) { … } /** * pm8001_init_sas_add - initialize sas address * @pm8001_ha: our ha struct. * * Currently we just set the fixed SAS address to our HBA, for manufacture, * it should read from the EEPROM */ static int pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) { … } /* * pm8001_get_phy_settings_info : Read phy setting values. * @pm8001_ha : our hba. */ static int pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha) { … } struct pm8001_mpi3_phy_pg_trx_config { … }; /** * pm8001_get_internal_phy_settings - Retrieves the internal PHY settings * @pm8001_ha : our adapter * @phycfg : PHY config page to populate */ static void pm8001_get_internal_phy_settings(struct pm8001_hba_info *pm8001_ha, struct pm8001_mpi3_phy_pg_trx_config *phycfg) { … } /** * pm8001_get_external_phy_settings - Retrieves the external PHY settings * @pm8001_ha : our adapter * @phycfg : PHY config page to populate */ static void pm8001_get_external_phy_settings(struct pm8001_hba_info *pm8001_ha, struct pm8001_mpi3_phy_pg_trx_config *phycfg) { … } /** * pm8001_get_phy_mask - Retrieves the mask that denotes if a PHY is int/ext * @pm8001_ha : our adapter * @phymask : The PHY mask */ static void pm8001_get_phy_mask(struct pm8001_hba_info *pm8001_ha, int *phymask) { … } /** * pm8001_set_phy_settings_ven_117c_12G() - Configure ATTO 12Gb PHY settings * @pm8001_ha : our adapter */ static int pm8001_set_phy_settings_ven_117c_12G(struct pm8001_hba_info *pm8001_ha) { … } /** * pm8001_configure_phy_settings - Configures PHY settings based on vendor ID. * @pm8001_ha : our hba. */ static int pm8001_configure_phy_settings(struct pm8001_hba_info *pm8001_ha) { … } /** * pm8001_setup_msix - enable MSI-X interrupt * @pm8001_ha: our ha struct. */ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) { … } static u32 pm8001_request_msix(struct pm8001_hba_info *pm8001_ha) { … } /** * pm8001_request_irq - register interrupt * @pm8001_ha: our ha struct. */ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha) { … } static void pm8001_free_irq(struct pm8001_hba_info *pm8001_ha) { … } /** * pm8001_pci_probe - probe supported device * @pdev: pci device which kernel has been prepared for. * @ent: pci device id * * This function is the main initialization function, when register a new * pci driver it is invoked, all struct and hardware initialization should be * done here, also, register interrupt. */ static int pm8001_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { … } /** * pm8001_init_ccb_tag - allocate memory to CCB and tag. * @pm8001_ha: our hba card information. */ static int pm8001_init_ccb_tag(struct pm8001_hba_info *pm8001_ha) { … } static void pm8001_pci_remove(struct pci_dev *pdev) { … } /** * pm8001_pci_suspend - power management suspend main entry point * @dev: Device struct * * Return: 0 on success, anything else on error. */ static int __maybe_unused pm8001_pci_suspend(struct device *dev) { … } /** * pm8001_pci_resume - power management resume main entry point * @dev: Device struct * * Return: 0 on success, anything else on error. */ static int __maybe_unused pm8001_pci_resume(struct device *dev) { … } /* update of pci device, vendor id and driver data with * unique value for each of the controller */ static struct pci_device_id pm8001_pci_table[] = …; static SIMPLE_DEV_PM_OPS(pm8001_pci_pm_ops, pm8001_pci_suspend, pm8001_pci_resume); static struct pci_driver pm8001_pci_driver = …; /** * pm8001_init - initialize scsi transport template */ static int __init pm8001_init(void) { … } static void __exit pm8001_exit(void) { … } module_init(…) …; module_exit(pm8001_exit); MODULE_AUTHOR(…) …; MODULE_AUTHOR(…) …; MODULE_AUTHOR(…) …; MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_VERSION(…); MODULE_LICENSE(…) …; MODULE_DEVICE_TABLE(pci, pm8001_pci_table);