^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Aic94xx SAS/SATA driver initialization.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2005 Adaptec, Inc. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <scsi/scsi_host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "aic94xx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "aic94xx_reg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "aic94xx_hwi.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "aic94xx_seq.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "aic94xx_sds.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /* The format is "version.release.patchlevel" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define ASD_DRIVER_VERSION "1.0.3"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static int use_msi = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) module_param_named(use_msi, use_msi, int, S_IRUGO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) MODULE_PARM_DESC(use_msi, "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) "\tEnable(1) or disable(0) using PCI MSI.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) "\tDefault: 0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static struct scsi_transport_template *aic94xx_transport_template;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static int asd_scan_finished(struct Scsi_Host *, unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static void asd_scan_start(struct Scsi_Host *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static struct scsi_host_template aic94xx_sht = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) .module = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* .name is initialized */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .name = "aic94xx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) .queuecommand = sas_queuecommand,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) .dma_need_drain = ata_scsi_dma_need_drain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) .target_alloc = sas_target_alloc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) .slave_configure = sas_slave_configure,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .scan_finished = asd_scan_finished,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .scan_start = asd_scan_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .change_queue_depth = sas_change_queue_depth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) .bios_param = sas_bios_param,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) .can_queue = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) .this_id = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .sg_tablesize = SG_ALL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) .max_sectors = SCSI_DEFAULT_MAX_SECTORS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) .eh_device_reset_handler = sas_eh_device_reset_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) .eh_target_reset_handler = sas_eh_target_reset_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) .slave_alloc = sas_slave_alloc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) .target_destroy = sas_target_destroy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) .ioctl = sas_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) .compat_ioctl = sas_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) .track_queue_depth = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static int asd_map_memio(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) int err, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct asd_ha_addrspace *io_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) asd_ha->iospace = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) for (i = 0; i < 3; i += 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) io_handle = &asd_ha->io_handle[i==0?0:1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) io_handle->start = pci_resource_start(asd_ha->pcidev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) io_handle->len = pci_resource_len(asd_ha->pcidev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) io_handle->flags = pci_resource_flags(asd_ha->pcidev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (!io_handle->start || !io_handle->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) asd_printk("MBAR%d start or length for %s is 0.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) i==0?0:1, pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) goto Err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) err = pci_request_region(asd_ha->pcidev, i, ASD_DRIVER_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) asd_printk("couldn't reserve memory region for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) goto Err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) io_handle->addr = ioremap(io_handle->start, io_handle->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (!io_handle->addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) asd_printk("couldn't map MBAR%d of %s\n", i==0?0:1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) goto Err_unreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) Err_unreq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) pci_release_region(asd_ha->pcidev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) Err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (i > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) io_handle = &asd_ha->io_handle[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) iounmap(io_handle->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) pci_release_region(asd_ha->pcidev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static void asd_unmap_memio(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct asd_ha_addrspace *io_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) io_handle = &asd_ha->io_handle[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) iounmap(io_handle->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) pci_release_region(asd_ha->pcidev, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) io_handle = &asd_ha->io_handle[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) iounmap(io_handle->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) pci_release_region(asd_ha->pcidev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static int asd_map_ioport(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) int i = PCI_IOBAR_OFFSET, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct asd_ha_addrspace *io_handle = &asd_ha->io_handle[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) asd_ha->iospace = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) io_handle->start = pci_resource_start(asd_ha->pcidev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) io_handle->len = pci_resource_len(asd_ha->pcidev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) io_handle->flags = pci_resource_flags(asd_ha->pcidev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) io_handle->addr = (void __iomem *) io_handle->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (!io_handle->start || !io_handle->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) asd_printk("couldn't get IO ports for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) err = pci_request_region(asd_ha->pcidev, i, ASD_DRIVER_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) asd_printk("couldn't reserve io space for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static void asd_unmap_ioport(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) pci_release_region(asd_ha->pcidev, PCI_IOBAR_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static int asd_map_ha(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) u16 cmd_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) err = pci_read_config_word(asd_ha->pcidev, PCI_COMMAND, &cmd_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) asd_printk("couldn't read command register of %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) goto Err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (cmd_reg & PCI_COMMAND_MEMORY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if ((err = asd_map_memio(asd_ha)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) goto Err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) } else if (cmd_reg & PCI_COMMAND_IO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if ((err = asd_map_ioport(asd_ha)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) goto Err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) asd_printk("%s ioport mapped -- upgrade your hardware\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) asd_printk("no proper device access to %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) goto Err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) Err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static void asd_unmap_ha(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (asd_ha->iospace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) asd_unmap_ioport(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) asd_unmap_memio(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static const char *asd_dev_rev[30] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) [0] = "A0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) [1] = "A1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) [8] = "B0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static int asd_common_setup(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) int err, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) asd_ha->revision_id = asd_ha->pcidev->revision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (asd_ha->revision_id < AIC9410_DEV_REV_B0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) asd_printk("%s is revision %s (%X), which is not supported\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) pci_name(asd_ha->pcidev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) asd_dev_rev[asd_ha->revision_id],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) asd_ha->revision_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) goto Err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /* Provide some sane default values. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) asd_ha->hw_prof.max_scbs = 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) asd_ha->hw_prof.max_ddbs = ASD_MAX_DDBS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) asd_ha->hw_prof.num_phys = ASD_MAX_PHYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /* All phys are enabled, by default. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) asd_ha->hw_prof.enabled_phys = 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) for (i = 0; i < ASD_MAX_PHYS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) asd_ha->hw_prof.phy_desc[i].max_sas_lrate =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) SAS_LINK_RATE_3_0_GBPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) asd_ha->hw_prof.phy_desc[i].min_sas_lrate =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) SAS_LINK_RATE_1_5_GBPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) asd_ha->hw_prof.phy_desc[i].max_sata_lrate =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) SAS_LINK_RATE_1_5_GBPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) asd_ha->hw_prof.phy_desc[i].min_sata_lrate =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) SAS_LINK_RATE_1_5_GBPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) Err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) static int asd_aic9410_setup(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) int err = asd_common_setup(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) asd_ha->hw_prof.addr_range = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) asd_ha->hw_prof.port_name_base = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) asd_ha->hw_prof.dev_name_base = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) asd_ha->hw_prof.sata_name_base = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static int asd_aic9405_setup(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) int err = asd_common_setup(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) asd_ha->hw_prof.addr_range = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) asd_ha->hw_prof.port_name_base = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) asd_ha->hw_prof.dev_name_base = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) asd_ha->hw_prof.sata_name_base = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static ssize_t asd_show_dev_rev(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) struct asd_ha_struct *asd_ha = dev_to_asd_ha(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return snprintf(buf, PAGE_SIZE, "%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) asd_dev_rev[asd_ha->revision_id]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static DEVICE_ATTR(aic_revision, S_IRUGO, asd_show_dev_rev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static ssize_t asd_show_dev_bios_build(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct device_attribute *attr,char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) struct asd_ha_struct *asd_ha = dev_to_asd_ha(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return snprintf(buf, PAGE_SIZE, "%d\n", asd_ha->hw_prof.bios.bld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) static DEVICE_ATTR(bios_build, S_IRUGO, asd_show_dev_bios_build, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static ssize_t asd_show_dev_pcba_sn(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) struct asd_ha_struct *asd_ha = dev_to_asd_ha(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return snprintf(buf, PAGE_SIZE, "%s\n", asd_ha->hw_prof.pcba_sn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static DEVICE_ATTR(pcba_sn, S_IRUGO, asd_show_dev_pcba_sn, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) #define FLASH_CMD_NONE 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) #define FLASH_CMD_UPDATE 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) #define FLASH_CMD_VERIFY 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) struct flash_command {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) u8 command[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) int code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) static struct flash_command flash_command_table[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {"verify", FLASH_CMD_VERIFY},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {"update", FLASH_CMD_UPDATE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {"", FLASH_CMD_NONE} /* Last entry should be NULL. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) struct error_bios {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) char *reason;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) int err_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static struct error_bios flash_error_table[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) {"Failed to open bios image file", FAIL_OPEN_BIOS_FILE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {"PCI ID mismatch", FAIL_CHECK_PCI_ID},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {"Checksum mismatch", FAIL_CHECK_SUM},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) {"Unknown Error", FAIL_UNKNOWN},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {"Failed to verify.", FAIL_VERIFY},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {"Failed to reset flash chip.", FAIL_RESET_FLASH},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {"Failed to find flash chip type.", FAIL_FIND_FLASH_ID},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {"Failed to erash flash chip.", FAIL_ERASE_FLASH},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {"Failed to program flash chip.", FAIL_WRITE_FLASH},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) {"Flash in progress", FLASH_IN_PROGRESS},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {"Image file size Error", FAIL_FILE_SIZE},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {"Input parameter error", FAIL_PARAMETERS},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {"Out of memory", FAIL_OUT_MEMORY},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {"OK", 0} /* Last entry err_code = 0. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) static ssize_t asd_store_update_bios(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) struct asd_ha_struct *asd_ha = dev_to_asd_ha(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) char *cmd_ptr, *filename_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) struct bios_file_header header, *hdr_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) int res, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) u32 csum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) int flash_command = FLASH_CMD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) cmd_ptr = kcalloc(count, 2, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (!cmd_ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) err = FAIL_OUT_MEMORY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) filename_ptr = cmd_ptr + count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) res = sscanf(buf, "%s %s", cmd_ptr, filename_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (res != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) err = FAIL_PARAMETERS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) goto out1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) for (i = 0; flash_command_table[i].code != FLASH_CMD_NONE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (!memcmp(flash_command_table[i].command,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) cmd_ptr, strlen(cmd_ptr))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) flash_command = flash_command_table[i].code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (flash_command == FLASH_CMD_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) err = FAIL_PARAMETERS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) goto out1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (asd_ha->bios_status == FLASH_IN_PROGRESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) err = FLASH_IN_PROGRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) goto out1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) err = request_firmware(&asd_ha->bios_image,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) filename_ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) &asd_ha->pcidev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) asd_printk("Failed to load bios image file %s, error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) filename_ptr, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) err = FAIL_OPEN_BIOS_FILE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) goto out1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) hdr_ptr = (struct bios_file_header *)asd_ha->bios_image->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if ((hdr_ptr->contrl_id.vendor != asd_ha->pcidev->vendor ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) hdr_ptr->contrl_id.device != asd_ha->pcidev->device) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) (hdr_ptr->contrl_id.sub_vendor != asd_ha->pcidev->vendor ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) hdr_ptr->contrl_id.sub_device != asd_ha->pcidev->device)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) ASD_DPRINTK("The PCI vendor or device id does not match\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) ASD_DPRINTK("vendor=%x dev=%x sub_vendor=%x sub_dev=%x"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) " pci vendor=%x pci dev=%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) hdr_ptr->contrl_id.vendor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) hdr_ptr->contrl_id.device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) hdr_ptr->contrl_id.sub_vendor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) hdr_ptr->contrl_id.sub_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) asd_ha->pcidev->vendor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) asd_ha->pcidev->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) err = FAIL_CHECK_PCI_ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) goto out2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (hdr_ptr->filelen != asd_ha->bios_image->size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) err = FAIL_FILE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) goto out2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /* calculate checksum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) for (i = 0; i < hdr_ptr->filelen; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) csum += asd_ha->bios_image->data[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if ((csum & 0x0000ffff) != hdr_ptr->checksum) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) ASD_DPRINTK("BIOS file checksum mismatch\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) err = FAIL_CHECK_SUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) goto out2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (flash_command == FLASH_CMD_UPDATE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) asd_ha->bios_status = FLASH_IN_PROGRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) err = asd_write_flash_seg(asd_ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) &asd_ha->bios_image->data[sizeof(*hdr_ptr)],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 0, hdr_ptr->filelen-sizeof(*hdr_ptr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) err = asd_verify_flash_seg(asd_ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) &asd_ha->bios_image->data[sizeof(*hdr_ptr)],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 0, hdr_ptr->filelen-sizeof(*hdr_ptr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) asd_ha->bios_status = FLASH_IN_PROGRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) err = asd_verify_flash_seg(asd_ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) &asd_ha->bios_image->data[sizeof(header)],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 0, hdr_ptr->filelen-sizeof(header));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) out2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) release_firmware(asd_ha->bios_image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) out1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) kfree(cmd_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) asd_ha->bios_status = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return -err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) static ssize_t asd_show_update_bios(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) struct asd_ha_struct *asd_ha = dev_to_asd_ha(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) for (i = 0; flash_error_table[i].err_code != 0; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (flash_error_table[i].err_code == asd_ha->bios_status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (asd_ha->bios_status != FLASH_IN_PROGRESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) asd_ha->bios_status = FLASH_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) return snprintf(buf, PAGE_SIZE, "status=%x %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) flash_error_table[i].err_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) flash_error_table[i].reason);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static DEVICE_ATTR(update_bios, S_IRUGO|S_IWUSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) asd_show_update_bios, asd_store_update_bios);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) static int asd_create_dev_attrs(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) err = device_create_file(&asd_ha->pcidev->dev, &dev_attr_aic_revision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) err = device_create_file(&asd_ha->pcidev->dev, &dev_attr_bios_build);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) goto err_rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) err = device_create_file(&asd_ha->pcidev->dev, &dev_attr_pcba_sn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) goto err_biosb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) err = device_create_file(&asd_ha->pcidev->dev, &dev_attr_update_bios);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) goto err_update_bios;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) err_update_bios:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) device_remove_file(&asd_ha->pcidev->dev, &dev_attr_pcba_sn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) err_biosb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) device_remove_file(&asd_ha->pcidev->dev, &dev_attr_bios_build);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) err_rev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) device_remove_file(&asd_ha->pcidev->dev, &dev_attr_aic_revision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) static void asd_remove_dev_attrs(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) device_remove_file(&asd_ha->pcidev->dev, &dev_attr_aic_revision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) device_remove_file(&asd_ha->pcidev->dev, &dev_attr_bios_build);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) device_remove_file(&asd_ha->pcidev->dev, &dev_attr_pcba_sn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) device_remove_file(&asd_ha->pcidev->dev, &dev_attr_update_bios);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) /* The first entry, 0, is used for dynamic ids, the rest for devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) * we know about.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static const struct asd_pcidev_struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) const char * name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) int (*setup)(struct asd_ha_struct *asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) } asd_pcidev_data[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) /* Id 0 is used for dynamic ids. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) { .name = "Adaptec AIC-94xx SAS/SATA Host Adapter",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) .setup = asd_aic9410_setup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) { .name = "Adaptec AIC-9410W SAS/SATA Host Adapter",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) .setup = asd_aic9410_setup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) { .name = "Adaptec AIC-9405W SAS/SATA Host Adapter",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) .setup = asd_aic9405_setup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) static int asd_create_ha_caches(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) asd_ha->scb_pool = dma_pool_create(ASD_DRIVER_NAME "_scb_pool",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) &asd_ha->pcidev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) sizeof(struct scb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 8, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (!asd_ha->scb_pool) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) asd_printk("couldn't create scb pool\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * asd_free_edbs -- free empty data buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) * asd_ha: pointer to host adapter structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) static void asd_free_edbs(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) struct asd_seq_data *seq = &asd_ha->seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) for (i = 0; i < seq->num_edbs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) asd_free_coherent(asd_ha, seq->edb_arr[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) kfree(seq->edb_arr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) seq->edb_arr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) static void asd_free_escbs(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) struct asd_seq_data *seq = &asd_ha->seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) for (i = 0; i < seq->num_escbs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (!list_empty(&seq->escb_arr[i]->list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) list_del_init(&seq->escb_arr[i]->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) asd_ascb_free(seq->escb_arr[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) kfree(seq->escb_arr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) seq->escb_arr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) static void asd_destroy_ha_caches(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (asd_ha->hw_prof.ddb_ext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) asd_free_coherent(asd_ha, asd_ha->hw_prof.ddb_ext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (asd_ha->hw_prof.scb_ext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) asd_free_coherent(asd_ha, asd_ha->hw_prof.scb_ext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) kfree(asd_ha->hw_prof.ddb_bitmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) asd_ha->hw_prof.ddb_bitmap = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) for (i = 0; i < ASD_MAX_PHYS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) struct asd_phy *phy = &asd_ha->phys[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) asd_free_coherent(asd_ha, phy->id_frm_tok);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (asd_ha->seq.escb_arr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) asd_free_escbs(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if (asd_ha->seq.edb_arr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) asd_free_edbs(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (asd_ha->hw_prof.ue.area) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) kfree(asd_ha->hw_prof.ue.area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) asd_ha->hw_prof.ue.area = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if (asd_ha->seq.tc_index_array) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) kfree(asd_ha->seq.tc_index_array);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) kfree(asd_ha->seq.tc_index_bitmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) asd_ha->seq.tc_index_array = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) asd_ha->seq.tc_index_bitmap = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (asd_ha->seq.actual_dl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) asd_free_coherent(asd_ha, asd_ha->seq.actual_dl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) asd_ha->seq.actual_dl = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) asd_ha->seq.dl = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (asd_ha->seq.next_scb.vaddr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) dma_pool_free(asd_ha->scb_pool, asd_ha->seq.next_scb.vaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) asd_ha->seq.next_scb.dma_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) asd_ha->seq.next_scb.vaddr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) dma_pool_destroy(asd_ha->scb_pool);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) asd_ha->scb_pool = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) struct kmem_cache *asd_dma_token_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) struct kmem_cache *asd_ascb_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) static int asd_create_global_caches(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) if (!asd_dma_token_cache) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) asd_dma_token_cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) = kmem_cache_create(ASD_DRIVER_NAME "_dma_token",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) sizeof(struct asd_dma_tok),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) SLAB_HWCACHE_ALIGN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (!asd_dma_token_cache) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) asd_printk("couldn't create dma token cache\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (!asd_ascb_cache) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) asd_ascb_cache = kmem_cache_create(ASD_DRIVER_NAME "_ascb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) sizeof(struct asd_ascb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) SLAB_HWCACHE_ALIGN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (!asd_ascb_cache) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) asd_printk("couldn't create ascb cache\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) goto Err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) Err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) kmem_cache_destroy(asd_dma_token_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) asd_dma_token_cache = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) static void asd_destroy_global_caches(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) kmem_cache_destroy(asd_dma_token_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) asd_dma_token_cache = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) kmem_cache_destroy(asd_ascb_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) asd_ascb_cache = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) static int asd_register_sas_ha(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) struct asd_sas_phy **sas_phys =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) kcalloc(ASD_MAX_PHYS, sizeof(*sas_phys), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) struct asd_sas_port **sas_ports =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) kcalloc(ASD_MAX_PHYS, sizeof(*sas_ports), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if (!sas_phys || !sas_ports) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) kfree(sas_phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) kfree(sas_ports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) asd_ha->sas_ha.sas_ha_name = (char *) asd_ha->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) asd_ha->sas_ha.lldd_module = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) asd_ha->sas_ha.sas_addr = &asd_ha->hw_prof.sas_addr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) for (i = 0; i < ASD_MAX_PHYS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) sas_phys[i] = &asd_ha->phys[i].sas_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) sas_ports[i] = &asd_ha->ports[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) asd_ha->sas_ha.sas_phy = sas_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) asd_ha->sas_ha.sas_port= sas_ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) asd_ha->sas_ha.num_phys= ASD_MAX_PHYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) return sas_register_ha(&asd_ha->sas_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) static int asd_unregister_sas_ha(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) err = sas_unregister_ha(&asd_ha->sas_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) sas_remove_host(asd_ha->sas_ha.core.shost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) scsi_host_put(asd_ha->sas_ha.core.shost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) kfree(asd_ha->sas_ha.sas_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) kfree(asd_ha->sas_ha.sas_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) static int asd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) const struct asd_pcidev_struct *asd_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) unsigned asd_id = (unsigned) id->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) struct asd_ha_struct *asd_ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) struct Scsi_Host *shost;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (asd_id >= ARRAY_SIZE(asd_pcidev_data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) asd_printk("wrong driver_data in PCI table\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if ((err = pci_enable_device(dev))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) asd_printk("couldn't enable device %s\n", pci_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) pci_set_master(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) shost = scsi_host_alloc(&aic94xx_sht, sizeof(void *));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) if (!shost)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) goto Err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) asd_dev = &asd_pcidev_data[asd_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) asd_ha = kzalloc(sizeof(*asd_ha), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (!asd_ha) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) asd_printk("out of memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) goto Err_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) asd_ha->pcidev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) asd_ha->sas_ha.dev = &asd_ha->pcidev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) asd_ha->sas_ha.lldd_ha = asd_ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) asd_ha->bios_status = FLASH_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) asd_ha->name = asd_dev->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) asd_printk("found %s, device %s\n", asd_ha->name, pci_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) SHOST_TO_SAS_HA(shost) = &asd_ha->sas_ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) asd_ha->sas_ha.core.shost = shost;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) shost->transportt = aic94xx_transport_template;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) shost->max_id = ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) shost->max_lun = ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) shost->max_cmd_len = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) err = scsi_add_host(shost, &dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) goto Err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) err = asd_dev->setup(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) goto Err_remove;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) err = dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) err = dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) asd_printk("no suitable DMA mask for %s\n", pci_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) goto Err_remove;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) pci_set_drvdata(dev, asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) err = asd_map_ha(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) goto Err_remove;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) err = asd_create_ha_caches(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) goto Err_unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) err = asd_init_hw(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) goto Err_free_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) asd_printk("device %s: SAS addr %llx, PCBA SN %s, %d phys, %d enabled "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) "phys, flash %s, BIOS %s%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) pci_name(dev), SAS_ADDR(asd_ha->hw_prof.sas_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) asd_ha->hw_prof.pcba_sn, asd_ha->hw_prof.max_phys,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) asd_ha->hw_prof.num_phys,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) asd_ha->hw_prof.flash.present ? "present" : "not present",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) asd_ha->hw_prof.bios.present ? "build " : "not present",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) asd_ha->hw_prof.bios.bld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) shost->can_queue = asd_ha->seq.can_queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (use_msi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) pci_enable_msi(asd_ha->pcidev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) err = request_irq(asd_ha->pcidev->irq, asd_hw_isr, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) ASD_DRIVER_NAME, asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) asd_printk("couldn't get irq %d for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) asd_ha->pcidev->irq, pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) goto Err_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) asd_enable_ints(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) err = asd_init_post_escbs(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) asd_printk("couldn't post escbs for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) pci_name(asd_ha->pcidev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) goto Err_escbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) ASD_DPRINTK("escbs posted\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) err = asd_create_dev_attrs(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) goto Err_dev_attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) err = asd_register_sas_ha(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) goto Err_reg_sas;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) scsi_scan_host(shost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) Err_reg_sas:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) asd_remove_dev_attrs(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) Err_dev_attrs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) Err_escbs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) asd_disable_ints(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) free_irq(dev->irq, asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) Err_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (use_msi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) pci_disable_msi(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) asd_chip_hardrst(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) Err_free_cache:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) asd_destroy_ha_caches(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) Err_unmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) asd_unmap_ha(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) Err_remove:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) scsi_remove_host(shost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) Err_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) kfree(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) Err_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) scsi_host_put(shost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) Err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) pci_disable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) static void asd_free_queues(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) LIST_HEAD(pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) struct list_head *n, *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) spin_lock_irqsave(&asd_ha->seq.pend_q_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) asd_ha->seq.pending = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) list_splice_init(&asd_ha->seq.pend_q, &pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) spin_unlock_irqrestore(&asd_ha->seq.pend_q_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (!list_empty(&pending))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) ASD_DPRINTK("Uh-oh! Pending is not empty!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) list_for_each_safe(pos, n, &pending) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) struct asd_ascb *ascb = list_entry(pos, struct asd_ascb, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) * Delete unexpired ascb timers. This may happen if we issue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) * a CONTROL PHY scb to an adapter and rmmod before the scb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) * times out. Apparently we don't wait for the CONTROL PHY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) * to complete, so it doesn't matter if we kill the timer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) del_timer_sync(&ascb->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) WARN_ON(ascb->scb->header.opcode != CONTROL_PHY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) list_del_init(pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) ASD_DPRINTK("freeing from pending\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) asd_ascb_free(ascb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) static void asd_turn_off_leds(struct asd_ha_struct *asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) u8 phy_mask = asd_ha->hw_prof.enabled_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) u8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) for_each_phy(phy_mask, phy_mask, i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) asd_turn_led(asd_ha, i, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) asd_control_led(asd_ha, i, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) static void asd_pci_remove(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) struct asd_ha_struct *asd_ha = pci_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) if (!asd_ha)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) asd_unregister_sas_ha(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) asd_disable_ints(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) asd_remove_dev_attrs(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) /* XXX more here as needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) free_irq(dev->irq, asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) if (use_msi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) pci_disable_msi(asd_ha->pcidev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) asd_turn_off_leds(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) asd_chip_hardrst(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) asd_free_queues(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) asd_destroy_ha_caches(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) asd_unmap_ha(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) kfree(asd_ha);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) pci_disable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) static void asd_scan_start(struct Scsi_Host *shost)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) struct asd_ha_struct *asd_ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) asd_ha = SHOST_TO_SAS_HA(shost)->lldd_ha;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) err = asd_enable_phys(asd_ha, asd_ha->hw_prof.enabled_phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) asd_printk("Couldn't enable phys, err:%d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) static int asd_scan_finished(struct Scsi_Host *shost, unsigned long time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) /* give the phy enabling interrupt event time to come in (1s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) * is empirically about all it takes) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if (time < HZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) /* Wait for discovery to finish */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) sas_drain_work(SHOST_TO_SAS_HA(shost));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) static ssize_t version_show(struct device_driver *driver, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) return snprintf(buf, PAGE_SIZE, "%s\n", ASD_DRIVER_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) static DRIVER_ATTR_RO(version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) static int asd_create_driver_attrs(struct device_driver *driver)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) return driver_create_file(driver, &driver_attr_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) static void asd_remove_driver_attrs(struct device_driver *driver)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) driver_remove_file(driver, &driver_attr_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) static struct sas_domain_function_template aic94xx_transport_functions = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) .lldd_dev_found = asd_dev_found,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) .lldd_dev_gone = asd_dev_gone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) .lldd_execute_task = asd_execute_task,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) .lldd_abort_task = asd_abort_task,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) .lldd_abort_task_set = asd_abort_task_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) .lldd_clear_aca = asd_clear_aca,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) .lldd_clear_task_set = asd_clear_task_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) .lldd_I_T_nexus_reset = asd_I_T_nexus_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) .lldd_lu_reset = asd_lu_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) .lldd_query_task = asd_query_task,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) .lldd_clear_nexus_port = asd_clear_nexus_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) .lldd_clear_nexus_ha = asd_clear_nexus_ha,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) .lldd_control_phy = asd_control_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) .lldd_ata_set_dmamode = asd_set_dmamode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) static const struct pci_device_id aic94xx_pci_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x410),0, 0, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x412),0, 0, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x416),0, 0, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x41E),0, 0, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x41F),0, 0, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x430),0, 0, 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x432),0, 0, 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x43E),0, 0, 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x43F),0, 0, 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) MODULE_DEVICE_TABLE(pci, aic94xx_pci_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) static struct pci_driver aic94xx_pci_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) .name = ASD_DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) .id_table = aic94xx_pci_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) .probe = asd_pci_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) .remove = asd_pci_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) static int __init aic94xx_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) asd_printk("%s version %s loaded\n", ASD_DRIVER_DESCRIPTION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) ASD_DRIVER_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) err = asd_create_global_caches();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) aic94xx_transport_template =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) sas_domain_attach_transport(&aic94xx_transport_functions);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if (!aic94xx_transport_template) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) goto out_destroy_caches;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) err = pci_register_driver(&aic94xx_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) goto out_release_transport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) err = asd_create_driver_attrs(&aic94xx_pci_driver.driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) goto out_unregister_pcidrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) out_unregister_pcidrv:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) pci_unregister_driver(&aic94xx_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) out_release_transport:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) sas_release_transport(aic94xx_transport_template);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) out_destroy_caches:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) asd_destroy_global_caches();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) static void __exit aic94xx_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) asd_remove_driver_attrs(&aic94xx_pci_driver.driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) pci_unregister_driver(&aic94xx_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) sas_release_transport(aic94xx_transport_template);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) asd_release_firmware();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) asd_destroy_global_caches();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) asd_printk("%s version %s unloaded\n", ASD_DRIVER_DESCRIPTION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) ASD_DRIVER_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) module_init(aic94xx_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) module_exit(aic94xx_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) MODULE_AUTHOR("Luben Tuikov <luben_tuikov@adaptec.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) MODULE_DESCRIPTION(ASD_DRIVER_DESCRIPTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) MODULE_VERSION(ASD_DRIVER_VERSION);