diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2008-02-22 14:39:54 +1100 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2008-02-22 14:39:54 +1100 |
commit | 52156f9f30ad4cab67da87870352a78313ab4008 (patch) | |
tree | dbfdb5eff9372abc1b3ffb92a7481925a6af2bdd | |
parent | 1b28daee27e7fdd44cf73941f9e15473801ab7e9 (diff) | |
parent | 51fa0e12201561592bc4abc851a22a41cb8b112f (diff) |
Merge commit 'scsi/master'
-rw-r--r-- | drivers/scsi/aic94xx/aic94xx.h | 16 | ||||
-rw-r--r-- | drivers/scsi/aic94xx/aic94xx_hwi.c | 20 | ||||
-rw-r--r-- | drivers/scsi/aic94xx/aic94xx_init.c | 2 | ||||
-rw-r--r-- | drivers/scsi/gdth.c | 247 | ||||
-rw-r--r-- | drivers/scsi/gdth.h | 2 | ||||
-rw-r--r-- | drivers/scsi/ips.c | 18 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_scsi_host.c | 41 | ||||
-rw-r--r-- | include/scsi/libsas.h | 2 |
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_ */ |