summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2008-02-22 14:39:54 +1100
committerStephen Rothwell <sfr@canb.auug.org.au>2008-02-22 14:39:54 +1100
commit52156f9f30ad4cab67da87870352a78313ab4008 (patch)
treedbfdb5eff9372abc1b3ffb92a7481925a6af2bdd
parent1b28daee27e7fdd44cf73941f9e15473801ab7e9 (diff)
parent51fa0e12201561592bc4abc851a22a41cb8b112f (diff)
Merge commit 'scsi/master'
-rw-r--r--drivers/scsi/aic94xx/aic94xx.h16
-rw-r--r--drivers/scsi/aic94xx/aic94xx_hwi.c20
-rw-r--r--drivers/scsi/aic94xx/aic94xx_init.c2
-rw-r--r--drivers/scsi/gdth.c247
-rw-r--r--drivers/scsi/gdth.h2
-rw-r--r--drivers/scsi/ips.c18
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c41
-rw-r--r--include/scsi/libsas.h2
8 files changed, 180 insertions, 168 deletions
diff --git a/drivers/scsi/aic94xx/aic94xx.h b/drivers/scsi/aic94xx/aic94xx.h
index 32f513b1b78a..aee235fde34a 100644
--- a/drivers/scsi/aic94xx/aic94xx.h
+++ b/drivers/scsi/aic94xx/aic94xx.h
@@ -58,7 +58,6 @@
extern struct kmem_cache *asd_dma_token_cache;
extern struct kmem_cache *asd_ascb_cache;
-extern char sas_addr_str[2*SAS_ADDR_SIZE + 1];
static inline void asd_stringify_sas_addr(char *p, const u8 *sas_addr)
{
@@ -68,21 +67,6 @@ static inline void asd_stringify_sas_addr(char *p, const u8 *sas_addr)
*p = '\0';
}
-static inline void asd_destringify_sas_addr(u8 *sas_addr, const char *p)
-{
- int i;
- for (i = 0; i < SAS_ADDR_SIZE; i++) {
- u8 h, l;
- if (!*p)
- break;
- h = isdigit(*p) ? *p-'0' : *p-'A'+10;
- p++;
- l = isdigit(*p) ? *p-'0' : *p-'A'+10;
- p++;
- sas_addr[i] = (h<<4) | l;
- }
-}
-
struct asd_ha_struct;
struct asd_ascb;
diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c
index 098b5f39cd31..940a207a42fb 100644
--- a/drivers/scsi/aic94xx/aic94xx_hwi.c
+++ b/drivers/scsi/aic94xx/aic94xx_hwi.c
@@ -27,6 +27,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/module.h>
+#include <linux/firmware.h>
#include "aic94xx.h"
#include "aic94xx_reg.h"
@@ -38,16 +39,14 @@ u32 MBAR0_SWB_SIZE;
/* ---------- Initialization ---------- */
-static void asd_get_user_sas_addr(struct asd_ha_struct *asd_ha)
+static int asd_get_user_sas_addr(struct asd_ha_struct *asd_ha)
{
- extern char sas_addr_str[];
- /* If the user has specified a WWN it overrides other settings
- */
- if (sas_addr_str[0] != '\0')
- asd_destringify_sas_addr(asd_ha->hw_prof.sas_addr,
- sas_addr_str);
- else if (asd_ha->hw_prof.sas_addr[0] != 0)
- asd_stringify_sas_addr(sas_addr_str, asd_ha->hw_prof.sas_addr);
+ /* adapter came with a sas address */
+ if (asd_ha->hw_prof.sas_addr[0])
+ return 0;
+
+ return sas_request_addr(asd_ha->sas_ha.core.shost,
+ asd_ha->hw_prof.sas_addr);
}
static void asd_propagate_sas_addr(struct asd_ha_struct *asd_ha)
@@ -657,8 +656,7 @@ int asd_init_hw(struct asd_ha_struct *asd_ha)
asd_init_ctxmem(asd_ha);
- asd_get_user_sas_addr(asd_ha);
- if (!asd_ha->hw_prof.sas_addr[0]) {
+ if (asd_get_user_sas_addr(asd_ha)) {
asd_printk("No SAS Address provided for %s\n",
pci_name(asd_ha->pcidev));
err = -ENODEV;
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index 5d761eb67442..1824b0bb1846 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -56,8 +56,6 @@ MODULE_PARM_DESC(collector, "\n"
"\tThe aic94xx SAS LLDD supports both modes.\n"
"\tDefault: 0 (Direct Mode).\n");
-char sas_addr_str[2*SAS_ADDR_SIZE + 1] = "";
-
static struct scsi_transport_template *aic94xx_transport_template;
static int asd_scan_finished(struct Scsi_Host *, unsigned long);
static void asd_scan_start(struct Scsi_Host *);
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 6d67f5c0eb8e..ad9aff2ad4fc 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -595,125 +595,111 @@ static int __init gdth_search_isa(ulong32 bios_adr)
#endif /* CONFIG_ISA */
#ifdef CONFIG_PCI
-static void gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
- ushort vendor, ushort dev);
+static bool gdth_pci_registered;
-static int __init gdth_search_pci(gdth_pci_str *pcistr)
+static bool gdth_search_vortex(ushort device)
{
- ushort device, cnt;
-
- TRACE(("gdth_search_pci()\n"));
-
- cnt = 0;
- for (device = 0; device <= PCI_DEVICE_ID_VORTEX_GDT6555; ++device)
- gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device);
- for (device = PCI_DEVICE_ID_VORTEX_GDT6x17RP;
- device <= PCI_DEVICE_ID_VORTEX_GDTMAXRP; ++device)
- gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device);
- gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX,
- PCI_DEVICE_ID_VORTEX_GDTNEWRX);
- gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX,
- PCI_DEVICE_ID_VORTEX_GDTNEWRX2);
- gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_SRC);
- gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_SRC_XSCALE);
- return cnt;
+ if (device <= PCI_DEVICE_ID_VORTEX_GDT6555)
+ return true;
+ if (device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP &&
+ device <= PCI_DEVICE_ID_VORTEX_GDTMAXRP)
+ return true;
+ if (device == PCI_DEVICE_ID_VORTEX_GDTNEWRX ||
+ device == PCI_DEVICE_ID_VORTEX_GDTNEWRX2)
+ return true;
+ return false;
}
+static int gdth_pci_probe_one(gdth_pci_str *pcistr, gdth_ha_str **ha_out);
+static int gdth_pci_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent);
+static void gdth_pci_remove_one(struct pci_dev *pdev);
+static void gdth_remove_one(gdth_ha_str *ha);
+
/* Vortex only makes RAID controllers.
* We do not really want to specify all 550 ids here, so wildcard match.
*/
-static struct pci_device_id gdthtable[] __maybe_unused = {
- {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID},
- {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID},
- {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID},
- {0}
+static const struct pci_device_id gdthtable[] = {
+ { PCI_VDEVICE(VORTEX, PCI_ANY_ID) },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SRC) },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SRC_XSCALE) },
+ { } /* terminate list */
};
-MODULE_DEVICE_TABLE(pci,gdthtable);
+MODULE_DEVICE_TABLE(pci, gdthtable);
-static void __init gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
- ushort vendor, ushort device)
+static struct pci_driver gdth_pci_driver = {
+ .name = "gdth",
+ .id_table = gdthtable,
+ .probe = gdth_pci_init_one,
+ .remove = gdth_pci_remove_one,
+};
+
+static void gdth_pci_remove_one(struct pci_dev *pdev)
{
- ulong base0, base1, base2;
- struct pci_dev *pdev;
+ gdth_ha_str *ha = pci_get_drvdata(pdev);
+
+ pci_set_drvdata(pdev, NULL);
+
+ list_del(&ha->list);
+ gdth_remove_one(ha);
+
+ pci_disable_device(pdev);
+}
+
+static int gdth_pci_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ ushort vendor = pdev->vendor;
+ ushort device = pdev->device;
+ ulong base0, base1, base2;
+ int rc;
+ gdth_pci_str gdth_pcistr;
+ gdth_ha_str *ha = NULL;
- TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n",
- *cnt, vendor, device));
+ TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n",
+ gdth_ctr_count, vendor, device));
- pdev = NULL;
- while ((pdev = pci_get_device(vendor, device, pdev))
- != NULL) {
- if (pci_enable_device(pdev))
- continue;
- if (*cnt >= MAXHA) {
- pci_dev_put(pdev);
- return;
- }
+ memset(&gdth_pcistr, 0, sizeof(gdth_pcistr));
+
+ if (vendor == PCI_VENDOR_ID_VORTEX && !gdth_search_vortex(device))
+ return -ENODEV;
+
+ rc = pci_enable_device(pdev);
+ if (rc)
+ return rc;
+
+ if (gdth_ctr_count >= MAXHA)
+ return -EBUSY;
/* GDT PCI controller found, resources are already in pdev */
- pcistr[*cnt].pdev = pdev;
- pcistr[*cnt].irq = pdev->irq;
+ gdth_pcistr.pdev = pdev;
base0 = pci_resource_flags(pdev, 0);
base1 = pci_resource_flags(pdev, 1);
base2 = pci_resource_flags(pdev, 2);
if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */
device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */
if (!(base0 & IORESOURCE_MEM))
- continue;
- pcistr[*cnt].dpmem = pci_resource_start(pdev, 0);
+ return -ENODEV;
+ gdth_pcistr.dpmem = pci_resource_start(pdev, 0);
} else { /* GDT6110, GDT6120, .. */
if (!(base0 & IORESOURCE_MEM) ||
!(base2 & IORESOURCE_MEM) ||
!(base1 & IORESOURCE_IO))
- continue;
- pcistr[*cnt].dpmem = pci_resource_start(pdev, 2);
- pcistr[*cnt].io_mm = pci_resource_start(pdev, 0);
- pcistr[*cnt].io = pci_resource_start(pdev, 1);
+ return -ENODEV;
+ gdth_pcistr.dpmem = pci_resource_start(pdev, 2);
+ gdth_pcistr.io = pci_resource_start(pdev, 1);
}
TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n",
- pcistr[*cnt].pdev->bus->number,
- PCI_SLOT(pcistr[*cnt].pdev->devfn),
- pcistr[*cnt].irq, pcistr[*cnt].dpmem));
- (*cnt)++;
- }
-}
+ gdth_pcistr.pdev->bus->number,
+ PCI_SLOT(gdth_pcistr.pdev->devfn),
+ gdth_pcistr.irq,
+ gdth_pcistr.dpmem));
-static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt)
-{
- gdth_pci_str temp;
- int i, changed;
-
- TRACE(("gdth_sort_pci() cnt %d\n",cnt));
- if (cnt == 0)
- return;
+ rc = gdth_pci_probe_one(&gdth_pcistr, &ha);
+ if (rc)
+ return rc;
- do {
- changed = FALSE;
- for (i = 0; i < cnt-1; ++i) {
- if (!reverse_scan) {
- if ((pcistr[i].pdev->bus->number > pcistr[i+1].pdev->bus->number) ||
- (pcistr[i].pdev->bus->number == pcistr[i+1].pdev->bus->number &&
- PCI_SLOT(pcistr[i].pdev->devfn) >
- PCI_SLOT(pcistr[i+1].pdev->devfn))) {
- temp = pcistr[i];
- pcistr[i] = pcistr[i+1];
- pcistr[i+1] = temp;
- changed = TRUE;
- }
- } else {
- if ((pcistr[i].pdev->bus->number < pcistr[i+1].pdev->bus->number) ||
- (pcistr[i].pdev->bus->number == pcistr[i+1].pdev->bus->number &&
- PCI_SLOT(pcistr[i].pdev->devfn) <
- PCI_SLOT(pcistr[i+1].pdev->devfn))) {
- temp = pcistr[i];
- pcistr[i] = pcistr[i+1];
- pcistr[i+1] = temp;
- changed = TRUE;
- }
- }
- }
- } while (changed);
+ return 0;
}
#endif /* CONFIG_PCI */
@@ -913,7 +899,8 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
#endif /* CONFIG_ISA */
#ifdef CONFIG_PCI
-static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
+static int gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr,
+ gdth_ha_str *ha)
{
register gdt6_dpram_str __iomem *dp6_ptr;
register gdt6c_dpram_str __iomem *dp6c_ptr;
@@ -925,14 +912,14 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
TRACE(("gdth_init_pci()\n"));
- if (pcistr->pdev->vendor == PCI_VENDOR_ID_INTEL)
+ if (pdev->vendor == PCI_VENDOR_ID_INTEL)
ha->oem_id = OEM_ID_INTEL;
else
ha->oem_id = OEM_ID_ICP;
- ha->brd_phys = (pcistr->pdev->bus->number << 8) | (pcistr->pdev->devfn & 0xf8);
- ha->stype = (ulong32)pcistr->pdev->device;
- ha->irq = pcistr->irq;
- ha->pdev = pcistr->pdev;
+ ha->brd_phys = (pdev->bus->number << 8) | (pdev->devfn & 0xf8);
+ ha->stype = (ulong32)pdev->device;
+ ha->irq = pdev->irq;
+ ha->pdev = pdev;
if (ha->pdev->device <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000/B */
TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
@@ -960,8 +947,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
continue;
}
iounmap(ha->brd);
- pci_write_config_dword(pcistr->pdev,
- PCI_BASE_ADDRESS_0, i);
+ pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, i);
ha->brd = ioremap(i, sizeof(gdt6_dpram_str));
if (ha->brd == NULL) {
printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
@@ -1070,8 +1056,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
continue;
}
iounmap(ha->brd);
- pci_write_config_dword(pcistr->pdev,
- PCI_BASE_ADDRESS_2, i);
+ pci_write_config_dword(pdev, PCI_BASE_ADDRESS_2, i);
ha->brd = ioremap(i, sizeof(gdt6c_dpram_str));
if (ha->brd == NULL) {
printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
@@ -1163,16 +1148,16 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
}
/* manipulate config. space to enable DPMEM, start RP controller */
- pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command);
+ pci_read_config_word(pdev, PCI_COMMAND, &command);
command |= 6;
- pci_write_config_word(pcistr->pdev, PCI_COMMAND, command);
- if (pci_resource_start(pcistr->pdev, 8) == 1UL)
- pci_resource_start(pcistr->pdev, 8) = 0UL;
+ pci_write_config_word(pdev, PCI_COMMAND, command);
+ if (pci_resource_start(pdev, 8) == 1UL)
+ pci_resource_start(pdev, 8) = 0UL;
i = 0xFEFF0001UL;
- pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, i);
+ pci_write_config_dword(pdev, PCI_ROM_ADDRESS, i);
gdth_delay(1);
- pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS,
- pci_resource_start(pcistr->pdev, 8));
+ pci_write_config_dword(pdev, PCI_ROM_ADDRESS,
+ pci_resource_start(pdev, 8));
dp6m_ptr = ha->brd;
@@ -1199,8 +1184,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
continue;
}
iounmap(ha->brd);
- pci_write_config_dword(pcistr->pdev,
- PCI_BASE_ADDRESS_0, i);
+ pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, i);
ha->brd = ioremap(i, sizeof(gdt6m_dpram_str));
if (ha->brd == NULL) {
printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
@@ -4998,12 +4982,16 @@ static int __init gdth_eisa_probe_one(ushort eisa_slot)
#endif /* CONFIG_EISA */
#ifdef CONFIG_PCI
-static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
+static int gdth_pci_probe_one(gdth_pci_str *pcistr,
+ gdth_ha_str **ha_out)
{
struct Scsi_Host *shp;
gdth_ha_str *ha;
dma_addr_t scratch_dma_handle = 0;
int error, i;
+ struct pci_dev *pdev = pcistr->pdev;
+
+ *ha_out = NULL;
shp = scsi_host_alloc(&gdth_template, sizeof(gdth_ha_str));
if (!shp)
@@ -5011,13 +4999,13 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
ha = shost_priv(shp);
error = -ENODEV;
- if (!gdth_init_pci(&pcistr[ctr],ha))
+ if (!gdth_init_pci(pdev, pcistr, ha))
goto out_host_put;
/* controller found and initialized */
printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n",
- pcistr[ctr].pdev->bus->number,
- PCI_SLOT(pcistr[ctr].pdev->devfn),
+ pdev->bus->number,
+ PCI_SLOT(pdev->devfn),
ha->irq);
error = request_irq(ha->irq, gdth_interrupt,
@@ -5062,7 +5050,7 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
ha->scratch_busy = FALSE;
ha->req_first = NULL;
- ha->tid_cnt = pcistr[ctr].pdev->device >= 0x200 ? MAXID : MAX_HDRIVES;
+ ha->tid_cnt = pdev->device >= 0x200 ? MAXID : MAX_HDRIVES;
if (max_ids > 0 && max_ids < ha->tid_cnt)
ha->tid_cnt = max_ids;
for (i = 0; i < GDTH_MAXCMDS; ++i)
@@ -5082,16 +5070,16 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
/* 64-bit DMA only supported from FW >= x.43 */
if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) ||
!ha->dma64_support) {
- if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) {
+ if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "GDT-PCI %d: "
"Unable to set 32-bit DMA\n", ha->hanum);
goto out_free_coal_stat;
}
} else {
shp->max_cmd_len = 16;
- if (!pci_set_dma_mask(pcistr[ctr].pdev, DMA_64BIT_MASK)) {
+ if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
printk("GDT-PCI %d: 64-bit DMA enabled\n", ha->hanum);
- } else if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) {
+ } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "GDT-PCI %d: "
"Unable to set 64/32-bit DMA\n", ha->hanum);
goto out_free_coal_stat;
@@ -5105,13 +5093,17 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
spin_lock_init(&ha->smp_lock);
gdth_enable_int(ha);
- error = scsi_add_host(shp, &pcistr[ctr].pdev->dev);
+ error = scsi_add_host(shp, &pdev->dev);
if (error)
goto out_free_coal_stat;
list_add_tail(&ha->list, &gdth_instances);
+ pci_set_drvdata(ha->pdev, ha);
+
scsi_scan_host(shp);
+ *ha_out = ha;
+
return 0;
out_free_coal_stat:
@@ -5210,16 +5202,8 @@ static int __init gdth_init(void)
#ifdef CONFIG_PCI
/* scanning for PCI controllers */
- {
- gdth_pci_str pcistr[MAXHA];
- int cnt,ctr;
-
- cnt = gdth_search_pci(pcistr);
- printk("GDT-HA: Found %d PCI Storage RAID Controllers\n", cnt);
- gdth_sort_pci(pcistr,cnt);
- for (ctr = 0; ctr < cnt; ++ctr)
- gdth_pci_probe_one(pcistr, ctr);
- }
+ if (pci_register_driver(&gdth_pci_driver) == 0)
+ gdth_pci_registered = true;
#endif /* CONFIG_PCI */
TRACE2(("gdth_detect() %d controller detected\n", gdth_ctr_count));
@@ -5246,6 +5230,11 @@ static void __exit gdth_exit(void)
{
gdth_ha_str *ha;
+#ifdef CONFIG_PCI
+ if (gdth_pci_registered)
+ pci_unregister_driver(&gdth_pci_driver);
+#endif
+
list_for_each_entry(ha, &gdth_instances, list)
gdth_remove_one(ha);
diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h
index 1434c6b0297c..8193f4b38d66 100644
--- a/drivers/scsi/gdth.h
+++ b/drivers/scsi/gdth.h
@@ -839,8 +839,6 @@ typedef struct {
struct pci_dev *pdev;
ulong dpmem; /* DPRAM address */
ulong io; /* IO address */
- ulong io_mm; /* IO address mem. mapped */
- unchar irq; /* IRQ */
} gdth_pci_str;
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 7ed568f180ae..e5467a4c225b 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -3510,15 +3510,16 @@ ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count)
struct scatterlist *sg = scsi_sglist(scmd);
for (i = 0, xfer_cnt = 0;
- (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) {
- min_cnt = min(count - xfer_cnt, sg[i].length);
+ (i < scsi_sg_count(scmd)) && (xfer_cnt < count);
+ i++, sg = sg_next(sg)) {
+ min_cnt = min(count - xfer_cnt, sg->length);
/* kmap_atomic() ensures addressability of the data buffer.*/
/* local_irq_save() protects the KM_IRQ0 address slot. */
local_irq_save(flags);
- buffer = kmap_atomic(sg_page(&sg[i]), KM_IRQ0) + sg[i].offset;
+ buffer = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
memcpy(buffer, &cdata[xfer_cnt], min_cnt);
- kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
+ kunmap_atomic(buffer - sg->offset, KM_IRQ0);
local_irq_restore(flags);
xfer_cnt += min_cnt;
@@ -3543,15 +3544,16 @@ ips_scmd_buf_read(struct scsi_cmnd *scmd, void *data, unsigned int count)
struct scatterlist *sg = scsi_sglist(scmd);
for (i = 0, xfer_cnt = 0;
- (i < scsi_sg_count(scmd)) && (xfer_cnt < count); i++) {
- min_cnt = min(count - xfer_cnt, sg[i].length);
+ (i < scsi_sg_count(scmd)) && (xfer_cnt < count);
+ i++, sg = sg_next(sg)) {
+ min_cnt = min(count - xfer_cnt, sg->length);
/* kmap_atomic() ensures addressability of the data buffer.*/
/* local_irq_save() protects the KM_IRQ0 address slot. */
local_irq_save(flags);
- buffer = kmap_atomic(sg_page(&sg[i]), KM_IRQ0) + sg[i].offset;
+ buffer = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
memcpy(&cdata[xfer_cnt], buffer, min_cnt);
- kunmap_atomic(buffer - sg[i].offset, KM_IRQ0);
+ kunmap_atomic(buffer - sg->offset, KM_IRQ0);
local_irq_restore(flags);
xfer_cnt += min_cnt;
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index b656e2919234..a4d980c3b399 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -24,6 +24,8 @@
*/
#include <linux/kthread.h>
+#include <linux/firmware.h>
+#include <linux/ctype.h>
#include "sas_internal.h"
@@ -1055,6 +1057,45 @@ void sas_target_destroy(struct scsi_target *starget)
return;
}
+static void sas_parse_addr(u8 *sas_addr, const char *p)
+{
+ int i;
+ for (i = 0; i < SAS_ADDR_SIZE; i++) {
+ u8 h, l;
+ if (!*p)
+ break;
+ h = isdigit(*p) ? *p-'0' : toupper(*p)-'A'+10;
+ p++;
+ l = isdigit(*p) ? *p-'0' : toupper(*p)-'A'+10;
+ p++;
+ sas_addr[i] = (h<<4) | l;
+ }
+}
+
+#define SAS_STRING_ADDR_SIZE 16
+
+int sas_request_addr(struct Scsi_Host *shost, u8 *addr)
+{
+ int res;
+ const struct firmware *fw;
+
+ res = request_firmware(&fw, "sas_addr", &shost->shost_gendev);
+ if (res)
+ return res;
+
+ if (fw->size < SAS_STRING_ADDR_SIZE) {
+ res = -ENODEV;
+ goto out;
+ }
+
+ sas_parse_addr(addr, fw->data);
+
+out:
+ release_firmware(fw);
+ return res;
+}
+EXPORT_SYMBOL_GPL(sas_request_addr);
+
EXPORT_SYMBOL_GPL(sas_queuecommand);
EXPORT_SYMBOL_GPL(sas_target_alloc);
EXPORT_SYMBOL_GPL(sas_slave_configure);
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 3ffd6b582a97..5f183de18dc9 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -676,4 +676,6 @@ extern int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
extern void sas_ssp_task_response(struct device *dev, struct sas_task *task,
struct ssp_response_iu *iu);
+int sas_request_addr(struct Scsi_Host *shost, u8 *addr);
+
#endif /* _SASLIB_H_ */