diff options
Diffstat (limited to 'drivers')
839 files changed, 21577 insertions, 17314 deletions
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 569ee090343f..46b58abb08c5 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -352,13 +352,16 @@ static int acpi_lpss_create_device(struct acpi_device *adev, pdata->mmio_size = resource_size(rentry->res); pdata->mmio_base = ioremap(rentry->res->start, pdata->mmio_size); - if (!pdata->mmio_base) - goto err_out; break; } acpi_dev_free_resource_list(&resource_list); + if (!pdata->mmio_base) { + ret = -ENOMEM; + goto err_out; + } + pdata->dev_desc = dev_desc; if (dev_desc->setup) diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 717afcdb5f4a..88dbbb115285 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -231,7 +231,7 @@ int acpi_device_set_power(struct acpi_device *device, int state) dev_warn(&device->dev, "Failed to change power state to %s\n", acpi_power_state_string(state)); } else { - device->power.state = state; + device->power.state = target_state; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] transitioned to %s\n", device->pnp.bus_id, diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c index 2161fa178c8d..628a42c41ab1 100644 --- a/drivers/acpi/nfit.c +++ b/drivers/acpi/nfit.c @@ -18,6 +18,7 @@ #include <linux/list.h> #include <linux/acpi.h> #include <linux/sort.h> +#include <linux/pmem.h> #include <linux/io.h> #include "nfit.h" @@ -305,6 +306,23 @@ static bool add_idt(struct acpi_nfit_desc *acpi_desc, return true; } +static bool add_flush(struct acpi_nfit_desc *acpi_desc, + struct acpi_nfit_flush_address *flush) +{ + struct device *dev = acpi_desc->dev; + struct nfit_flush *nfit_flush = devm_kzalloc(dev, sizeof(*nfit_flush), + GFP_KERNEL); + + if (!nfit_flush) + return false; + INIT_LIST_HEAD(&nfit_flush->list); + nfit_flush->flush = flush; + list_add_tail(&nfit_flush->list, &acpi_desc->flushes); + dev_dbg(dev, "%s: nfit_flush handle: %d hint_count: %d\n", __func__, + flush->device_handle, flush->hint_count); + return true; +} + static void *add_table(struct acpi_nfit_desc *acpi_desc, void *table, const void *end) { @@ -338,7 +356,8 @@ static void *add_table(struct acpi_nfit_desc *acpi_desc, void *table, return err; break; case ACPI_NFIT_TYPE_FLUSH_ADDRESS: - dev_dbg(dev, "%s: flush\n", __func__); + if (!add_flush(acpi_desc, table)) + return err; break; case ACPI_NFIT_TYPE_SMBIOS: dev_dbg(dev, "%s: smbios\n", __func__); @@ -389,6 +408,7 @@ static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc, { u16 dcr = __to_nfit_memdev(nfit_mem)->region_index; struct nfit_memdev *nfit_memdev; + struct nfit_flush *nfit_flush; struct nfit_dcr *nfit_dcr; struct nfit_bdw *nfit_bdw; struct nfit_idt *nfit_idt; @@ -442,6 +462,14 @@ static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc, nfit_mem->idt_bdw = nfit_idt->idt; break; } + + list_for_each_entry(nfit_flush, &acpi_desc->flushes, list) { + if (nfit_flush->flush->device_handle != + nfit_memdev->memdev->device_handle) + continue; + nfit_mem->nfit_flush = nfit_flush; + break; + } break; } @@ -978,6 +1006,24 @@ static u64 to_interleave_offset(u64 offset, struct nfit_blk_mmio *mmio) return mmio->base_offset + line_offset + table_offset + sub_line_offset; } +static void wmb_blk(struct nfit_blk *nfit_blk) +{ + + if (nfit_blk->nvdimm_flush) { + /* + * The first wmb() is needed to 'sfence' all previous writes + * such that they are architecturally visible for the platform + * buffer flush. Note that we've already arranged for pmem + * writes to avoid the cache via arch_memcpy_to_pmem(). The + * final wmb() ensures ordering for the NVDIMM flush write. + */ + wmb(); + writeq(1, nfit_blk->nvdimm_flush); + wmb(); + } else + wmb_pmem(); +} + static u64 read_blk_stat(struct nfit_blk *nfit_blk, unsigned int bw) { struct nfit_blk_mmio *mmio = &nfit_blk->mmio[DCR]; @@ -1012,7 +1058,10 @@ static void write_blk_ctl(struct nfit_blk *nfit_blk, unsigned int bw, offset = to_interleave_offset(offset, mmio); writeq(cmd, mmio->base + offset); - /* FIXME: conditionally perform read-back if mandated by firmware */ + wmb_blk(nfit_blk); + + if (nfit_blk->dimm_flags & ND_BLK_DCR_LATCH) + readq(mmio->base + offset); } static int acpi_nfit_blk_single_io(struct nfit_blk *nfit_blk, @@ -1026,7 +1075,6 @@ static int acpi_nfit_blk_single_io(struct nfit_blk *nfit_blk, base_offset = nfit_blk->bdw_offset + dpa % L1_CACHE_BYTES + lane * mmio->size; - /* TODO: non-temporal access, flush hints, cache management etc... */ write_blk_ctl(nfit_blk, lane, dpa, len, rw); while (len) { unsigned int c; @@ -1045,13 +1093,19 @@ static int acpi_nfit_blk_single_io(struct nfit_blk *nfit_blk, } if (rw) - memcpy(mmio->aperture + offset, iobuf + copied, c); + memcpy_to_pmem(mmio->aperture + offset, + iobuf + copied, c); else - memcpy(iobuf + copied, mmio->aperture + offset, c); + memcpy_from_pmem(iobuf + copied, + mmio->aperture + offset, c); copied += c; len -= c; } + + if (rw) + wmb_blk(nfit_blk); + rc = read_blk_stat(nfit_blk, lane) ? -EIO : 0; return rc; } @@ -1124,7 +1178,7 @@ static void nfit_spa_unmap(struct acpi_nfit_desc *acpi_desc, } static void __iomem *__nfit_spa_map(struct acpi_nfit_desc *acpi_desc, - struct acpi_nfit_system_address *spa) + struct acpi_nfit_system_address *spa, enum spa_map_type type) { resource_size_t start = spa->address; resource_size_t n = spa->length; @@ -1152,8 +1206,15 @@ static void __iomem *__nfit_spa_map(struct acpi_nfit_desc *acpi_desc, if (!res) goto err_mem; - /* TODO: cacheability based on the spa type */ - spa_map->iomem = ioremap_nocache(start, n); + if (type == SPA_MAP_APERTURE) { + /* + * TODO: memremap_pmem() support, but that requires cache + * flushing when the aperture is moved. + */ + spa_map->iomem = ioremap_wc(start, n); + } else + spa_map->iomem = ioremap_nocache(start, n); + if (!spa_map->iomem) goto err_map; @@ -1171,6 +1232,7 @@ static void __iomem *__nfit_spa_map(struct acpi_nfit_desc *acpi_desc, * nfit_spa_map - interleave-aware managed-mappings of acpi_nfit_system_address ranges * @nvdimm_bus: NFIT-bus that provided the spa table entry * @nfit_spa: spa table to map + * @type: aperture or control region * * In the case where block-data-window apertures and * dimm-control-regions are interleaved they will end up sharing a @@ -1180,12 +1242,12 @@ static void __iomem *__nfit_spa_map(struct acpi_nfit_desc *acpi_desc, * unbound. */ static void __iomem *nfit_spa_map(struct acpi_nfit_desc *acpi_desc, - struct acpi_nfit_system_address *spa) + struct acpi_nfit_system_address *spa, enum spa_map_type type) { void __iomem *iomem; mutex_lock(&acpi_desc->spa_map_mutex); - iomem = __nfit_spa_map(acpi_desc, spa); + iomem = __nfit_spa_map(acpi_desc, spa, type); mutex_unlock(&acpi_desc->spa_map_mutex); return iomem; @@ -1206,12 +1268,35 @@ static int nfit_blk_init_interleave(struct nfit_blk_mmio *mmio, return 0; } +static int acpi_nfit_blk_get_flags(struct nvdimm_bus_descriptor *nd_desc, + struct nvdimm *nvdimm, struct nfit_blk *nfit_blk) +{ + struct nd_cmd_dimm_flags flags; + int rc; + + memset(&flags, 0, sizeof(flags)); + rc = nd_desc->ndctl(nd_desc, nvdimm, ND_CMD_DIMM_FLAGS, &flags, + sizeof(flags)); + + if (rc >= 0 && flags.status == 0) + nfit_blk->dimm_flags = flags.flags; + else if (rc == -ENOTTY) { + /* fall back to a conservative default */ + nfit_blk->dimm_flags = ND_BLK_DCR_LATCH; + rc = 0; + } else + rc = -ENXIO; + + return rc; +} + static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus, struct device *dev) { struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus); struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc); struct nd_blk_region *ndbr = to_nd_blk_region(dev); + struct nfit_flush *nfit_flush; struct nfit_blk_mmio *mmio; struct nfit_blk *nfit_blk; struct nfit_mem *nfit_mem; @@ -1223,8 +1308,8 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus, if (!nfit_mem || !nfit_mem->dcr || !nfit_mem->bdw) { dev_dbg(dev, "%s: missing%s%s%s\n", __func__, nfit_mem ? "" : " nfit_mem", - nfit_mem->dcr ? "" : " dcr", - nfit_mem->bdw ? "" : " bdw"); + (nfit_mem && nfit_mem->dcr) ? "" : " dcr", + (nfit_mem && nfit_mem->bdw) ? "" : " bdw"); return -ENXIO; } @@ -1237,7 +1322,8 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus, /* map block aperture memory */ nfit_blk->bdw_offset = nfit_mem->bdw->offset; mmio = &nfit_blk->mmio[BDW]; - mmio->base = nfit_spa_map(acpi_desc, nfit_mem->spa_bdw); + mmio->base = nfit_spa_map(acpi_desc, nfit_mem->spa_bdw, + SPA_MAP_APERTURE); if (!mmio->base) { dev_dbg(dev, "%s: %s failed to map bdw\n", __func__, nvdimm_name(nvdimm)); @@ -1259,7 +1345,8 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus, nfit_blk->cmd_offset = nfit_mem->dcr->command_offset; nfit_blk->stat_offset = nfit_mem->dcr->status_offset; mmio = &nfit_blk->mmio[DCR]; - mmio->base = nfit_spa_map(acpi_desc, nfit_mem->spa_dcr); + mmio->base = nfit_spa_map(acpi_desc, nfit_mem->spa_dcr, + SPA_MAP_CONTROL); if (!mmio->base) { dev_dbg(dev, "%s: %s failed to map dcr\n", __func__, nvdimm_name(nvdimm)); @@ -1277,6 +1364,24 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus, return rc; } + rc = acpi_nfit_blk_get_flags(nd_desc, nvdimm, nfit_blk); + if (rc < 0) { + dev_dbg(dev, "%s: %s failed get DIMM flags\n", + __func__, nvdimm_name(nvdimm)); + return rc; + } + + nfit_flush = nfit_mem->nfit_flush; + if (nfit_flush && nfit_flush->flush->hint_count != 0) { + nfit_blk->nvdimm_flush = devm_ioremap_nocache(dev, + nfit_flush->flush->hint_address[0], 8); + if (!nfit_blk->nvdimm_flush) + return -ENOMEM; + } + + if (!arch_has_pmem_api() && !nfit_blk->nvdimm_flush) + dev_warn(dev, "unable to guarantee persistence of writes\n"); + if (mmio->line_size == 0) return 0; @@ -1459,6 +1564,7 @@ int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, acpi_size sz) INIT_LIST_HEAD(&acpi_desc->dcrs); INIT_LIST_HEAD(&acpi_desc->bdws); INIT_LIST_HEAD(&acpi_desc->idts); + INIT_LIST_HEAD(&acpi_desc->flushes); INIT_LIST_HEAD(&acpi_desc->memdevs); INIT_LIST_HEAD(&acpi_desc->dimms); mutex_init(&acpi_desc->spa_map_mutex); diff --git a/drivers/acpi/nfit.h b/drivers/acpi/nfit.h index 81f2e8c5a79c..79b6d83875c1 100644 --- a/drivers/acpi/nfit.h +++ b/drivers/acpi/nfit.h @@ -40,6 +40,10 @@ enum nfit_uuids { NFIT_UUID_MAX, }; +enum { + ND_BLK_DCR_LATCH = 2, +}; + struct nfit_spa { struct acpi_nfit_system_address *spa; struct list_head list; @@ -60,6 +64,11 @@ struct nfit_idt { struct list_head list; }; +struct nfit_flush { + struct acpi_nfit_flush_address *flush; + struct list_head list; +}; + struct nfit_memdev { struct acpi_nfit_memory_map *memdev; struct list_head list; @@ -77,6 +86,7 @@ struct nfit_mem { struct acpi_nfit_system_address *spa_bdw; struct acpi_nfit_interleave *idt_dcr; struct acpi_nfit_interleave *idt_bdw; + struct nfit_flush *nfit_flush; struct list_head list; struct acpi_device *adev; unsigned long dsm_mask; @@ -88,6 +98,7 @@ struct acpi_nfit_desc { struct mutex spa_map_mutex; struct list_head spa_maps; struct list_head memdevs; + struct list_head flushes; struct list_head dimms; struct list_head spas; struct list_head dcrs; @@ -109,7 +120,7 @@ struct nfit_blk { struct nfit_blk_mmio { union { void __iomem *base; - void *aperture; + void __pmem *aperture; }; u64 size; u64 base_offset; @@ -123,6 +134,13 @@ struct nfit_blk { u64 bdw_offset; /* post interleave offset */ u64 stat_offset; u64 cmd_offset; + void __iomem *nvdimm_flush; + u32 dimm_flags; +}; + +enum spa_map_type { + SPA_MAP_CONTROL, + SPA_MAP_APERTURE, }; struct nfit_spa_mapping { diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index c262e4acd68d..3b8963f21b36 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -175,10 +175,14 @@ static void __init acpi_request_region (struct acpi_generic_address *gas, if (!addr || !length) return; - acpi_reserve_region(addr, length, gas->space_id, 0, desc); + /* Resources are never freed */ + if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) + request_region(addr, length, desc); + else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) + request_mem_region(addr, length, desc); } -static void __init acpi_reserve_resources(void) +static int __init acpi_reserve_resources(void) { acpi_request_region(&acpi_gbl_FADT.xpm1a_event_block, acpi_gbl_FADT.pm1_event_length, "ACPI PM1a_EVT_BLK"); @@ -207,7 +211,10 @@ static void __init acpi_reserve_resources(void) if (!(acpi_gbl_FADT.gpe1_block_length & 0x1)) acpi_request_region(&acpi_gbl_FADT.xgpe1_block, acpi_gbl_FADT.gpe1_block_length, "ACPI GPE1_BLK"); + + return 0; } +fs_initcall_sync(acpi_reserve_resources); void acpi_os_printf(const char *fmt, ...) { @@ -1862,7 +1869,6 @@ acpi_status __init acpi_os_initialize(void) acpi_status __init acpi_os_initialize1(void) { - acpi_reserve_resources(); kacpid_wq = alloc_workqueue("kacpid", 0, 1); kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1); kacpi_hotplug_wq = alloc_ordered_workqueue("kacpi_hotplug", 0); diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 10561ce16ed1..f1c966e05078 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -26,7 +26,6 @@ #include <linux/device.h> #include <linux/export.h> #include <linux/ioport.h> -#include <linux/list.h> #include <linux/slab.h> #ifdef CONFIG_X86 @@ -194,6 +193,7 @@ static bool acpi_decode_space(struct resource_win *win, u8 iodec = attr->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16; bool wp = addr->info.mem.write_protect; u64 len = attr->address_length; + u64 start, end, offset = 0; struct resource *res = &win->res; /* @@ -205,9 +205,6 @@ static bool acpi_decode_space(struct resource_win *win, pr_debug("ACPI: Invalid address space min_addr_fix %d, max_addr_fix %d, len %llx\n", addr->min_address_fixed, addr->max_address_fixed, len); - res->start = attr->minimum; - res->end = attr->maximum; - /* * For bridges that translate addresses across the bridge, * translation_offset is the offset that must be added to the @@ -215,12 +212,22 @@ static bool acpi_decode_space(struct resource_win *win, * primary side. Non-bridge devices must list 0 for all Address * Translation offset bits. */ - if (addr->producer_consumer == ACPI_PRODUCER) { - res->start += attr->translation_offset; - res->end += attr->translation_offset; - } else if (attr->translation_offset) { + if (addr->producer_consumer == ACPI_PRODUCER) + offset = attr->translation_offset; + else if (attr->translation_offset) pr_debug("ACPI: translation_offset(%lld) is invalid for non-bridge device.\n", attr->translation_offset); + start = attr->minimum + offset; + end = attr->maximum + offset; + + win->offset = offset; + res->start = start; + res->end = end; + if (sizeof(resource_size_t) < sizeof(u64) && + (offset != win->offset || start != res->start || end != res->end)) { + pr_warn("acpi resource window ([%#llx-%#llx] ignored, not CPU addressable)\n", + attr->minimum, attr->maximum); + return false; } switch (addr->resource_type) { @@ -237,8 +244,6 @@ static bool acpi_decode_space(struct resource_win *win, return false; } - win->offset = attr->translation_offset; - if (addr->producer_consumer == ACPI_PRODUCER) res->flags |= IORESOURCE_WINDOW; @@ -622,164 +627,3 @@ int acpi_dev_filter_resource_type(struct acpi_resource *ares, return (type & types) ? 0 : 1; } EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type); - -struct reserved_region { - struct list_head node; - u64 start; - u64 end; -}; - -static LIST_HEAD(reserved_io_regions); -static LIST_HEAD(reserved_mem_regions); - -static int request_range(u64 start, u64 end, u8 space_id, unsigned long flags, - char *desc) -{ - unsigned int length = end - start + 1; - struct resource *res; - - res = space_id == ACPI_ADR_SPACE_SYSTEM_IO ? - request_region(start, length, desc) : - request_mem_region(start, length, desc); - if (!res) - return -EIO; - - res->flags &= ~flags; - return 0; -} - -static int add_region_before(u64 start, u64 end, u8 space_id, - unsigned long flags, char *desc, - struct list_head *head) -{ - struct reserved_region *reg; - int error; - - reg = kmalloc(sizeof(*reg), GFP_KERNEL); - if (!reg) - return -ENOMEM; - - error = request_range(start, end, space_id, flags, desc); - if (error) { - kfree(reg); - return error; - } - - reg->start = start; - reg->end = end; - list_add_tail(®->node, head); - return 0; -} - -/** - * acpi_reserve_region - Reserve an I/O or memory region as a system resource. - * @start: Starting address of the region. - * @length: Length of the region. - * @space_id: Identifier of address space to reserve the region from. - * @flags: Resource flags to clear for the region after requesting it. - * @desc: Region description (for messages). - * - * Reserve an I/O or memory region as a system resource to prevent others from - * using it. If the new region overlaps with one of the regions (in the given - * address space) already reserved by this routine, only the non-overlapping - * parts of it will be reserved. - * - * Returned is either 0 (success) or a negative error code indicating a resource - * reservation problem. It is the code of the first encountered error, but the - * routine doesn't abort until it has attempted to request all of the parts of - * the new region that don't overlap with other regions reserved previously. - * - * The resources requested by this routine are never released. - */ -int acpi_reserve_region(u64 start, unsigned int length, u8 space_id, - unsigned long flags, char *desc) -{ - struct list_head *regions; - struct reserved_region *reg; - u64 end = start + length - 1; - int ret = 0, error = 0; - - if (space_id == ACPI_ADR_SPACE_SYSTEM_IO) - regions = &reserved_io_regions; - else if (space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) - regions = &reserved_mem_regions; - else - return -EINVAL; - - if (list_empty(regions)) - return add_region_before(start, end, space_id, flags, desc, regions); - - list_for_each_entry(reg, regions, node) - if (reg->start == end + 1) { - /* The new region can be prepended to this one. */ - ret = request_range(start, end, space_id, flags, desc); - if (!ret) - reg->start = start; - - return ret; - } else if (reg->start > end) { - /* No overlap. Add the new region here and get out. */ - return add_region_before(start, end, space_id, flags, - desc, ®->node); - } else if (reg->end == start - 1) { - goto combine; - } else if (reg->end >= start) { - goto overlap; - } - - /* The new region goes after the last existing one. */ - return add_region_before(start, end, space_id, flags, desc, regions); - - overlap: - /* - * The new region overlaps an existing one. - * - * The head part of the new region immediately preceding the existing - * overlapping one can be combined with it right away. - */ - if (reg->start > start) { - error = request_range(start, reg->start - 1, space_id, flags, desc); - if (error) - ret = error; - else - reg->start = start; - } - - combine: - /* - * The new region is adjacent to an existing one. If it extends beyond - * that region all the way to the next one, it is possible to combine - * all three of them. - */ - while (reg->end < end) { - struct reserved_region *next = NULL; - u64 a = reg->end + 1, b = end; - - if (!list_is_last(®->node, regions)) { - next = list_next_entry(reg, node); - if (next->start <= end) - b = next->start - 1; - } - error = request_range(a, b, space_id, flags, desc); - if (!error) { - if (next && next->start == b + 1) { - reg->end = next->end; - list_del(&next->node); - kfree(next); - } else { - reg->end = end; - break; - } - } else if (next) { - if (!ret) - ret = error; - - reg = next; - } else { - break; - } - } - - return ret ? ret : error; -} -EXPORT_SYMBOL_GPL(acpi_reserve_region); diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 2649a068671d..ec256352f423 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1019,6 +1019,29 @@ static bool acpi_of_match_device(struct acpi_device *adev, return false; } +static bool __acpi_match_device_cls(const struct acpi_device_id *id, + struct acpi_hardware_id *hwid) +{ + int i, msk, byte_shift; + char buf[3]; + + if (!id->cls) + return false; + + /* Apply class-code bitmask, before checking each class-code byte */ + for (i = 1; i <= 3; i++) { + byte_shift = 8 * (3 - i); + msk = (id->cls_msk >> byte_shift) & 0xFF; + if (!msk) + continue; + + sprintf(buf, "%02x", (id->cls >> byte_shift) & msk); + if (strncmp(buf, &hwid->id[(i - 1) * 2], 2)) + return false; + } + return true; +} + static const struct acpi_device_id *__acpi_match_device( struct acpi_device *device, const struct acpi_device_id *ids, @@ -1036,9 +1059,12 @@ static const struct acpi_device_id *__acpi_match_device( list_for_each_entry(hwid, &device->pnp.ids, list) { /* First, check the ACPI/PNP IDs provided by the caller. */ - for (id = ids; id->id[0]; id++) - if (!strcmp((char *) id->id, hwid->id)) + for (id = ids; id->id[0] || id->cls; id++) { + if (id->id[0] && !strcmp((char *) id->id, hwid->id)) return id; + else if (id->cls && __acpi_match_device_cls(id, hwid)) + return id; + } /* * Next, check ACPI_DT_NAMESPACE_HID and try to match the @@ -2101,6 +2127,8 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp, if (info->valid & ACPI_VALID_UID) pnp->unique_id = kstrdup(info->unique_id.string, GFP_KERNEL); + if (info->valid & ACPI_VALID_CLS) + acpi_add_id(pnp, info->class_code.string); kfree(info); diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 6d17a3b65ef7..15e40ee62a94 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -48,7 +48,7 @@ config ATA_VERBOSE_ERROR config ATA_ACPI bool "ATA ACPI Support" - depends on ACPI && PCI + depends on ACPI default y help This option adds support for ATA-related ACPI objects. diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 614c78f510f0..1befb114c384 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -20,6 +20,8 @@ #include <linux/platform_device.h> #include <linux/libata.h> #include <linux/ahci_platform.h> +#include <linux/acpi.h> +#include <linux/pci_ids.h> #include "ahci.h" #define DRV_NAME "ahci" @@ -79,12 +81,19 @@ static const struct of_device_id ahci_of_match[] = { }; MODULE_DEVICE_TABLE(of, ahci_of_match); +static const struct acpi_device_id ahci_acpi_match[] = { + { ACPI_DEVICE_CLASS(PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff) }, + {}, +}; +MODULE_DEVICE_TABLE(acpi, ahci_acpi_match); + static struct platform_driver ahci_driver = { .probe = ahci_probe, .remove = ata_platform_remove_one, .driver = { .name = DRV_NAME, .of_match_table = ahci_of_match, + .acpi_match_table = ahci_acpi_match, .pm = &ahci_pm_ops, }, }; diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index e83fc3d0da9c..db5d9f79a247 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2478,6 +2478,10 @@ int ata_dev_configure(struct ata_device *dev) dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128, dev->max_sectors); + if (dev->horkage & ATA_HORKAGE_MAX_SEC_1024) + dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_1024, + dev->max_sectors); + if (dev->horkage & ATA_HORKAGE_MAX_SEC_LBA48) dev->max_sectors = ATA_MAX_SECTORS_LBA48; @@ -4146,6 +4150,12 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "Slimtype DVD A DS8A8SH", NULL, ATA_HORKAGE_MAX_SEC_LBA48 }, { "Slimtype DVD A DS8A9SH", NULL, ATA_HORKAGE_MAX_SEC_LBA48 }, + /* + * Causes silent data corruption with higher max sects. + * http://lkml.kernel.org/g/x49wpy40ysk.fsf@segfault.boston.devel.redhat.com + */ + { "ST380013AS", "3.20", ATA_HORKAGE_MAX_SEC_1024 }, + /* Devices we expect to fail diagnostics */ /* Devices where NCQ should be avoided */ @@ -4174,9 +4184,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "ST3320[68]13AS", "SD1[5-9]", ATA_HORKAGE_NONCQ | ATA_HORKAGE_FIRMWARE_WARN }, - /* Seagate Momentus SpinPoint M8 seem to have FPMDA_AA issues */ + /* drives which fail FPDMA_AA activation (some may freeze afterwards) */ { "ST1000LM024 HN-M101MBB", "2AR10001", ATA_HORKAGE_BROKEN_FPDMA_AA }, { "ST1000LM024 HN-M101MBB", "2BA30001", ATA_HORKAGE_BROKEN_FPDMA_AA }, + { "VB0250EAVER", "HPG7", ATA_HORKAGE_BROKEN_FPDMA_AA }, /* Blacklist entries taken from Silicon Image 3124/3132 Windows driver .inf file - also several Linux problem reports */ @@ -4229,7 +4240,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { ATA_HORKAGE_ZERO_AFTER_TRIM, }, { "Crucial_CT*M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | ATA_HORKAGE_ZERO_AFTER_TRIM, }, - { "Micron_M5[15]0*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM | + { "Micron_M5[15]0_*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM | ATA_HORKAGE_ZERO_AFTER_TRIM, }, { "Crucial_CT*M550*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM | ATA_HORKAGE_ZERO_AFTER_TRIM, }, @@ -4238,6 +4249,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "Samsung SSD 8*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | ATA_HORKAGE_ZERO_AFTER_TRIM, }, + /* devices that don't properly handle TRIM commands */ + { "SuperSSpeed S238*", NULL, ATA_HORKAGE_NOTRIM, }, + /* * As defined, the DRAT (Deterministic Read After Trim) and RZAT * (Return Zero After Trim) flags in the ATA Command Set are @@ -4501,7 +4515,8 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev) else /* In the ancient relic department - skip all of this */ return 0; - err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); + /* On some disks, this command causes spin-up, so we need longer timeout */ + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 15000); DPRINTK("EXIT, err_mask=%x\n", err_mask); return err_mask; diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index 7ccc084bf1df..85aa76116a30 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -460,6 +460,13 @@ static void sata_pmp_quirks(struct ata_port *ap) ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA; } + } else if (vendor == 0x11ab && devid == 0x4140) { + /* Marvell 4140 quirks */ + ata_for_each_link(link, ap, EDGE) { + /* port 4 is for SEMB device and it doesn't like SRST */ + if (link->pmp == 4) + link->flags |= ATA_LFLAG_DISABLED; + } } } diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 3131adcc1f87..641a61a59e89 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2568,7 +2568,8 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf) rbuf[14] = (lowest_aligned >> 8) & 0x3f; rbuf[15] = lowest_aligned; - if (ata_id_has_trim(args->id)) { + if (ata_id_has_trim(args->id) && + !(dev->horkage & ATA_HORKAGE_NOTRIM)) { rbuf[14] |= 0x80; /* LBPME */ if (ata_id_has_zero_after_trim(args->id) && diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c index d6c37bcd416d..e2d94972962d 100644 --- a/drivers/ata/libata-transport.c +++ b/drivers/ata/libata-transport.c @@ -569,6 +569,8 @@ show_ata_dev_trim(struct device *dev, if (!ata_id_has_trim(ata_dev->id)) mode = "unsupported"; + else if (ata_dev->horkage & ATA_HORKAGE_NOTRIM) + mode = "forced_unsupported"; else if (ata_dev->horkage & ATA_HORKAGE_NO_NCQ_TRIM) mode = "forced_unqueued"; else if (ata_fpdma_dsm_supported(ata_dev)) diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c index a9b0c820f2eb..5d9ee99c2148 100644 --- a/drivers/ata/pata_arasan_cf.c +++ b/drivers/ata/pata_arasan_cf.c @@ -4,7 +4,7 @@ * Arasan Compact Flash host controller source file * * Copyright (C) 2011 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -968,7 +968,7 @@ static struct platform_driver arasan_cf_driver = { module_platform_driver(arasan_cf_driver); -MODULE_AUTHOR("Viresh Kumar <viresh.linux@gmail.com>"); +MODULE_AUTHOR("Viresh Kumar <vireshk@kernel.org>"); MODULE_DESCRIPTION("Arasan ATA Compact Flash driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 9c4288362a8e..894bda114224 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -563,10 +563,8 @@ static void fw_dev_release(struct device *dev) kfree(fw_priv); } -static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) +static int do_firmware_uevent(struct firmware_priv *fw_priv, struct kobj_uevent_env *env) { - struct firmware_priv *fw_priv = to_firmware_priv(dev); - if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->buf->fw_id)) return -ENOMEM; if (add_uevent_var(env, "TIMEOUT=%i", loading_timeout)) @@ -577,6 +575,18 @@ static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) return 0; } +static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + struct firmware_priv *fw_priv = to_firmware_priv(dev); + int err = 0; + + mutex_lock(&fw_lock); + if (fw_priv->buf) + err = do_firmware_uevent(fw_priv, env); + mutex_unlock(&fw_lock); + return err; +} + static struct class firmware_class = { .name = "firmware", .class_attrs = firmware_class_attrs, diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index cdd547bd67df..0ee43c1056e0 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -6,6 +6,7 @@ * This file is released under the GPLv2. */ +#include <linux/delay.h> #include <linux/kernel.h> #include <linux/io.h> #include <linux/platform_device.h> @@ -19,6 +20,8 @@ #include <linux/suspend.h> #include <linux/export.h> +#define GENPD_RETRY_MAX_MS 250 /* Approximate */ + #define GENPD_DEV_CALLBACK(genpd, type, callback, dev) \ ({ \ type (*__routine)(struct device *__d); \ @@ -2131,6 +2134,7 @@ EXPORT_SYMBOL_GPL(of_genpd_get_from_provider); static void genpd_dev_pm_detach(struct device *dev, bool power_off) { struct generic_pm_domain *pd; + unsigned int i; int ret = 0; pd = pm_genpd_lookup_dev(dev); @@ -2139,10 +2143,12 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) dev_dbg(dev, "removing from PM domain %s\n", pd->name); - while (1) { + for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) { ret = pm_genpd_remove_device(pd, dev); if (ret != -EAGAIN) break; + + mdelay(i); cond_resched(); } @@ -2183,6 +2189,7 @@ int genpd_dev_pm_attach(struct device *dev) { struct of_phandle_args pd_args; struct generic_pm_domain *pd; + unsigned int i; int ret; if (!dev->of_node) @@ -2218,10 +2225,12 @@ int genpd_dev_pm_attach(struct device *dev) dev_dbg(dev, "adding to PM domain %s\n", pd->name); - while (1) { + for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) { ret = pm_genpd_add_device(pd, dev); if (ret != -EAGAIN) break; + + mdelay(i); cond_resched(); } diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c index 7470004ca810..eb6e67451dec 100644 --- a/drivers/base/power/wakeirq.c +++ b/drivers/base/power/wakeirq.c @@ -45,14 +45,12 @@ static int dev_pm_attach_wake_irq(struct device *dev, int irq, return -EEXIST; } - dev->power.wakeirq = wirq; - spin_unlock_irqrestore(&dev->power.lock, flags); - err = device_wakeup_attach_irq(dev, wirq); - if (err) - return err; + if (!err) + dev->power.wakeirq = wirq; - return 0; + spin_unlock_irqrestore(&dev->power.lock, flags); + return err; } /** @@ -105,10 +103,10 @@ void dev_pm_clear_wake_irq(struct device *dev) return; spin_lock_irqsave(&dev->power.lock, flags); + device_wakeup_detach_irq(dev); dev->power.wakeirq = NULL; spin_unlock_irqrestore(&dev->power.lock, flags); - device_wakeup_detach_irq(dev); if (wirq->dedicated_irq) free_irq(wirq->irq, wirq); kfree(wirq); diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index 40f71603378c..51f15bc15774 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c @@ -281,32 +281,25 @@ EXPORT_SYMBOL_GPL(device_wakeup_enable); * Attach a device wakeirq to the wakeup source so the device * wake IRQ can be configured automatically for suspend and * resume. + * + * Call under the device's power.lock lock. */ int device_wakeup_attach_irq(struct device *dev, struct wake_irq *wakeirq) { struct wakeup_source *ws; - int ret = 0; - spin_lock_irq(&dev->power.lock); ws = dev->power.wakeup; if (!ws) { dev_err(dev, "forgot to call call device_init_wakeup?\n"); - ret = -EINVAL; - goto unlock; + return -EINVAL; } - if (ws->wakeirq) { - ret = -EEXIST; - goto unlock; - } + if (ws->wakeirq) + return -EEXIST; ws->wakeirq = wakeirq; - -unlock: - spin_unlock_irq(&dev->power.lock); - - return ret; + return 0; } /** @@ -314,20 +307,16 @@ unlock: * @dev: Device to handle * * Removes a device wakeirq from the wakeup source. + * + * Call under the device's power.lock lock. */ void device_wakeup_detach_irq(struct device *dev) { struct wakeup_source *ws; - spin_lock_irq(&dev->power.lock); ws = dev->power.wakeup; - if (!ws) - goto unlock; - - ws->wakeirq = NULL; - -unlock: - spin_unlock_irq(&dev->power.lock); + if (ws) + ws->wakeirq = NULL; } /** diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c index 69de41a87b74..3177b245d2bd 100644 --- a/drivers/block/null_blk.c +++ b/drivers/block/null_blk.c @@ -240,19 +240,19 @@ static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer) while ((entry = llist_del_all(&cq->list)) != NULL) { entry = llist_reverse_order(entry); do { + struct request_queue *q = NULL; + cmd = container_of(entry, struct nullb_cmd, ll_list); entry = entry->next; + if (cmd->rq) + q = cmd->rq->q; end_cmd(cmd); - if (cmd->rq) { - struct request_queue *q = cmd->rq->q; - - if (!q->mq_ops && blk_queue_stopped(q)) { - spin_lock(q->queue_lock); - if (blk_queue_stopped(q)) - blk_start_queue(q); - spin_unlock(q->queue_lock); - } + if (q && !q->mq_ops && blk_queue_stopped(q)) { + spin_lock(q->queue_lock); + if (blk_queue_stopped(q)) + blk_start_queue(q); + spin_unlock(q->queue_lock); } } while (entry); } diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c index d1d6141920d3..7920c2741b47 100644 --- a/drivers/block/nvme-core.c +++ b/drivers/block/nvme-core.c @@ -2108,8 +2108,17 @@ static void nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid) goto out_free_disk; add_disk(ns->disk); - if (ns->ms) - revalidate_disk(ns->disk); + if (ns->ms) { + struct block_device *bd = bdget_disk(ns->disk, 0); + if (!bd) + return; + if (blkdev_get(bd, FMODE_READ, NULL)) { + bdput(bd); + return; + } + blkdev_reread_part(bd); + blkdev_put(bd, FMODE_READ); + } return; out_free_disk: kfree(disk); diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index d94529d5c8e9..bc67a93aa4f4 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -523,6 +523,7 @@ void rbd_warn(struct rbd_device *rbd_dev, const char *fmt, ...) # define rbd_assert(expr) ((void) 0) #endif /* !RBD_DEBUG */ +static void rbd_osd_copyup_callback(struct rbd_obj_request *obj_request); static int rbd_img_obj_request_submit(struct rbd_obj_request *obj_request); static void rbd_img_parent_read(struct rbd_obj_request *obj_request); static void rbd_dev_remove_parent(struct rbd_device *rbd_dev); @@ -1818,6 +1819,16 @@ static void rbd_osd_stat_callback(struct rbd_obj_request *obj_request) obj_request_done_set(obj_request); } +static void rbd_osd_call_callback(struct rbd_obj_request *obj_request) +{ + dout("%s: obj %p\n", __func__, obj_request); + + if (obj_request_img_data_test(obj_request)) + rbd_osd_copyup_callback(obj_request); + else + obj_request_done_set(obj_request); +} + static void rbd_osd_req_callback(struct ceph_osd_request *osd_req, struct ceph_msg *msg) { @@ -1866,6 +1877,8 @@ static void rbd_osd_req_callback(struct ceph_osd_request *osd_req, rbd_osd_discard_callback(obj_request); break; case CEPH_OSD_OP_CALL: + rbd_osd_call_callback(obj_request); + break; case CEPH_OSD_OP_NOTIFY_ACK: case CEPH_OSD_OP_WATCH: rbd_osd_trivial_callback(obj_request); @@ -2530,13 +2543,15 @@ out_unwind: } static void -rbd_img_obj_copyup_callback(struct rbd_obj_request *obj_request) +rbd_osd_copyup_callback(struct rbd_obj_request *obj_request) { struct rbd_img_request *img_request; struct rbd_device *rbd_dev; struct page **pages; u32 page_count; + dout("%s: obj %p\n", __func__, obj_request); + rbd_assert(obj_request->type == OBJ_REQUEST_BIO || obj_request->type == OBJ_REQUEST_NODATA); rbd_assert(obj_request_img_data_test(obj_request)); @@ -2563,9 +2578,7 @@ rbd_img_obj_copyup_callback(struct rbd_obj_request *obj_request) if (!obj_request->result) obj_request->xferred = obj_request->length; - /* Finish up with the normal image object callback */ - - rbd_img_obj_callback(obj_request); + obj_request_done_set(obj_request); } static void @@ -2650,7 +2663,6 @@ rbd_img_obj_parent_read_full_callback(struct rbd_img_request *img_request) /* All set, send it off. */ - orig_request->callback = rbd_img_obj_copyup_callback; osdc = &rbd_dev->rbd_client->client->osdc; img_result = rbd_obj_request_submit(osdc, orig_request); if (!img_result) diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index 1e1a4323a71f..9ceb8ac68fdc 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -472,12 +472,11 @@ int btbcm_setup_apple(struct hci_dev *hdev) /* Read Verbose Config Version Info */ skb = btbcm_read_verbose_config(hdev); - if (IS_ERR(skb)) - return PTR_ERR(skb); - - BT_INFO("%s: BCM: chip id %u build %4.4u", hdev->name, skb->data[1], - get_unaligned_le16(skb->data + 5)); - kfree_skb(skb); + if (!IS_ERR(skb)) { + BT_INFO("%s: BCM: chip id %u build %4.4u", hdev->name, skb->data[1], + get_unaligned_le16(skb->data + 5)); + kfree_skb(skb); + } set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index da8faf78536a..5643b65cee20 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -429,7 +429,7 @@ static int hwrng_fillfn(void *unused) static void start_khwrngd(void) { hwrng_fill = kthread_run(hwrng_fillfn, NULL, "hwrng"); - if (hwrng_fill == ERR_PTR(-ENOMEM)) { + if (IS_ERR(hwrng_fill)) { pr_err("hwrng_fill thread creation failed"); hwrng_fill = NULL; } diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 283f00a7f036..1082d4bb016a 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -129,8 +129,9 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev, device_initialize(&chip->dev); - chip->cdev.owner = chip->pdev->driver->owner; cdev_init(&chip->cdev, &tpm_fops); + chip->cdev.owner = chip->pdev->driver->owner; + chip->cdev.kobj.parent = &chip->dev.kobj; return chip; } diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index 44f9d20c19ac..1267322595da 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c @@ -233,6 +233,14 @@ static int crb_acpi_add(struct acpi_device *device) return -ENODEV; } + /* At least some versions of AMI BIOS have a bug that TPM2 table has + * zero address for the control area and therefore we must fail. + */ + if (!buf->control_area_pa) { + dev_err(dev, "TPM2 ACPI table has a zero address for the control area\n"); + return -EINVAL; + } + if (buf->hdr.length < sizeof(struct acpi_tpm2)) { dev_err(dev, "TPM2 ACPI table has wrong size"); return -EINVAL; diff --git a/drivers/clk/at91/clk-h32mx.c b/drivers/clk/at91/clk-h32mx.c index 152dcb3f7b5f..61566bcefa53 100644 --- a/drivers/clk/at91/clk-h32mx.c +++ b/drivers/clk/at91/clk-h32mx.c @@ -116,8 +116,10 @@ void __init of_sama5d4_clk_h32mx_setup(struct device_node *np, h32mxclk->pmc = pmc; clk = clk_register(NULL, &h32mxclk->hw); - if (!clk) + if (!clk) { + kfree(h32mxclk); return; + } of_clk_add_provider(np, of_clk_src_simple_get, clk); } diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c index c2400456a044..27dfa965cfed 100644 --- a/drivers/clk/at91/clk-main.c +++ b/drivers/clk/at91/clk-main.c @@ -171,8 +171,10 @@ at91_clk_register_main_osc(struct at91_pmc *pmc, irq_set_status_flags(osc->irq, IRQ_NOAUTOEN); ret = request_irq(osc->irq, clk_main_osc_irq_handler, IRQF_TRIGGER_HIGH, name, osc); - if (ret) + if (ret) { + kfree(osc); return ERR_PTR(ret); + } if (bypass) pmc_write(pmc, AT91_CKGR_MOR, diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c index f98eafe9b12d..5b3ded5205a2 100644 --- a/drivers/clk/at91/clk-master.c +++ b/drivers/clk/at91/clk-master.c @@ -165,12 +165,16 @@ at91_clk_register_master(struct at91_pmc *pmc, unsigned int irq, irq_set_status_flags(master->irq, IRQ_NOAUTOEN); ret = request_irq(master->irq, clk_master_irq_handler, IRQF_TRIGGER_HIGH, "clk-master", master); - if (ret) + if (ret) { + kfree(master); return ERR_PTR(ret); + } clk = clk_register(NULL, &master->hw); - if (IS_ERR(clk)) + if (IS_ERR(clk)) { + free_irq(master->irq, master); kfree(master); + } return clk; } diff --git a/drivers/clk/at91/clk-pll.c b/drivers/clk/at91/clk-pll.c index cbbe40377ad6..18b60f4895a6 100644 --- a/drivers/clk/at91/clk-pll.c +++ b/drivers/clk/at91/clk-pll.c @@ -346,12 +346,16 @@ at91_clk_register_pll(struct at91_pmc *pmc, unsigned int irq, const char *name, irq_set_status_flags(pll->irq, IRQ_NOAUTOEN); ret = request_irq(pll->irq, clk_pll_irq_handler, IRQF_TRIGGER_HIGH, id ? "clk-pllb" : "clk-plla", pll); - if (ret) + if (ret) { + kfree(pll); return ERR_PTR(ret); + } clk = clk_register(NULL, &pll->hw); - if (IS_ERR(clk)) + if (IS_ERR(clk)) { + free_irq(pll->irq, pll); kfree(pll); + } return clk; } diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c index a76d03fd577b..58008b3e8bc1 100644 --- a/drivers/clk/at91/clk-system.c +++ b/drivers/clk/at91/clk-system.c @@ -130,13 +130,17 @@ at91_clk_register_system(struct at91_pmc *pmc, const char *name, irq_set_status_flags(sys->irq, IRQ_NOAUTOEN); ret = request_irq(sys->irq, clk_system_irq_handler, IRQF_TRIGGER_HIGH, name, sys); - if (ret) + if (ret) { + kfree(sys); return ERR_PTR(ret); + } } clk = clk_register(NULL, &sys->hw); - if (IS_ERR(clk)) + if (IS_ERR(clk)) { + free_irq(sys->irq, sys); kfree(sys); + } return clk; } diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c index ae3263bc1476..30dd697b1668 100644 --- a/drivers/clk/at91/clk-utmi.c +++ b/drivers/clk/at91/clk-utmi.c @@ -118,12 +118,16 @@ at91_clk_register_utmi(struct at91_pmc *pmc, unsigned int irq, irq_set_status_flags(utmi->irq, IRQ_NOAUTOEN); ret = request_irq(utmi->irq, clk_utmi_irq_handler, IRQF_TRIGGER_HIGH, "clk-utmi", utmi); - if (ret) + if (ret) { + kfree(utmi); return ERR_PTR(ret); + } clk = clk_register(NULL, &utmi->hw); - if (IS_ERR(clk)) + if (IS_ERR(clk)) { + free_irq(utmi->irq, utmi); kfree(utmi); + } return clk; } diff --git a/drivers/clk/bcm/clk-iproc-asiu.c b/drivers/clk/bcm/clk-iproc-asiu.c index e19c09cd9645..f630e1bbdcfe 100644 --- a/drivers/clk/bcm/clk-iproc-asiu.c +++ b/drivers/clk/bcm/clk-iproc-asiu.c @@ -222,10 +222,6 @@ void __init iproc_asiu_setup(struct device_node *node, struct iproc_asiu_clk *asiu_clk; const char *clk_name; - clk_name = kzalloc(IPROC_CLK_NAME_LEN, GFP_KERNEL); - if (WARN_ON(!clk_name)) - goto err_clk_register; - ret = of_property_read_string_index(node, "clock-output-names", i, &clk_name); if (WARN_ON(ret)) @@ -259,7 +255,7 @@ void __init iproc_asiu_setup(struct device_node *node, err_clk_register: for (i = 0; i < num_clks; i++) - kfree(asiu->clks[i].name); + clk_unregister(asiu->clk_data.clks[i]); iounmap(asiu->gate_base); err_iomap_gate: diff --git a/drivers/clk/bcm/clk-iproc-pll.c b/drivers/clk/bcm/clk-iproc-pll.c index 46fb84bc2674..2dda4e8295a9 100644 --- a/drivers/clk/bcm/clk-iproc-pll.c +++ b/drivers/clk/bcm/clk-iproc-pll.c @@ -366,7 +366,7 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw, val = readl(pll->pll_base + ctrl->ndiv_int.offset); ndiv_int = (val >> ctrl->ndiv_int.shift) & bit_mask(ctrl->ndiv_int.width); - ndiv = ndiv_int << ctrl->ndiv_int.shift; + ndiv = (u64)ndiv_int << ctrl->ndiv_int.shift; if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) { val = readl(pll->pll_base + ctrl->ndiv_frac.offset); @@ -374,7 +374,8 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw, bit_mask(ctrl->ndiv_frac.width); if (ndiv_frac != 0) - ndiv = (ndiv_int << ctrl->ndiv_int.shift) | ndiv_frac; + ndiv = ((u64)ndiv_int << ctrl->ndiv_int.shift) | + ndiv_frac; } val = readl(pll->pll_base + ctrl->pdiv.offset); @@ -655,10 +656,6 @@ void __init iproc_pll_clk_setup(struct device_node *node, memset(&init, 0, sizeof(init)); parent_name = node->name; - clk_name = kzalloc(IPROC_CLK_NAME_LEN, GFP_KERNEL); - if (WARN_ON(!clk_name)) - goto err_clk_register; - ret = of_property_read_string_index(node, "clock-output-names", i, &clk_name); if (WARN_ON(ret)) @@ -690,10 +687,8 @@ void __init iproc_pll_clk_setup(struct device_node *node, return; err_clk_register: - for (i = 0; i < num_clks; i++) { - kfree(pll->clks[i].name); + for (i = 0; i < num_clks; i++) clk_unregister(pll->clk_data.clks[i]); - } err_pll_register: if (pll->asiu_base) diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c index b9b12a742970..3f6f7ad39490 100644 --- a/drivers/clk/clk-stm32f4.c +++ b/drivers/clk/clk-stm32f4.c @@ -268,7 +268,7 @@ static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary) memcpy(table, stm32f42xx_gate_map, sizeof(table)); /* only bits set in table can be used as indices */ - if (WARN_ON(secondary > 8 * sizeof(table) || + if (WARN_ON(secondary >= BITS_PER_BYTE * sizeof(table) || 0 == (table[BIT_ULL_WORD(secondary)] & BIT_ULL_MASK(secondary)))) return -EINVAL; diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c index 4b9e04cdf7e8..8b6523d15fb8 100644 --- a/drivers/clk/mediatek/clk-mt8173.c +++ b/drivers/clk/mediatek/clk-mt8173.c @@ -700,6 +700,22 @@ static const struct mtk_composite peri_clks[] __initconst = { MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1), }; +static struct clk_onecell_data *mt8173_top_clk_data __initdata; +static struct clk_onecell_data *mt8173_pll_clk_data __initdata; + +static void __init mtk_clk_enable_critical(void) +{ + if (!mt8173_top_clk_data || !mt8173_pll_clk_data) + return; + + clk_prepare_enable(mt8173_pll_clk_data->clks[CLK_APMIXED_ARMCA15PLL]); + clk_prepare_enable(mt8173_pll_clk_data->clks[CLK_APMIXED_ARMCA7PLL]); + clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_MEM_SEL]); + clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_DDRPHYCFG_SEL]); + clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_CCI400_SEL]); + clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_RTC_SEL]); +} + static void __init mtk_topckgen_init(struct device_node *node) { struct clk_onecell_data *clk_data; @@ -712,19 +728,19 @@ static void __init mtk_topckgen_init(struct device_node *node) return; } - clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + mt8173_top_clk_data = clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data); mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, &mt8173_clk_lock, clk_data); - clk_prepare_enable(clk_data->clks[CLK_TOP_CCI400_SEL]); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); + + mtk_clk_enable_critical(); } CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8173-topckgen", mtk_topckgen_init); @@ -818,13 +834,13 @@ static void __init mtk_apmixedsys_init(struct device_node *node) { struct clk_onecell_data *clk_data; - clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + mt8173_pll_clk_data = clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); if (!clk_data) return; mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); - clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMCA15PLL]); + mtk_clk_enable_critical(); } CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys", mtk_apmixedsys_init); diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index b95d17fbb8d7..92936f0912d2 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -530,19 +530,16 @@ static int clk_pixel_set_rate(struct clk_hw *hw, unsigned long rate, struct clk_rcg2 *rcg = to_clk_rcg2(hw); struct freq_tbl f = *rcg->freq_tbl; const struct frac_entry *frac = frac_table_pixel; - unsigned long request, src_rate; + unsigned long request; int delta = 100000; u32 mask = BIT(rcg->hid_width) - 1; u32 hid_div; - int index = qcom_find_src_index(hw, rcg->parent_map, f.src); - struct clk *parent = clk_get_parent_by_index(hw->clk, index); for (; frac->num; frac++) { request = (rate * frac->den) / frac->num; - src_rate = __clk_round_rate(parent, request); - if ((src_rate < (request - delta)) || - (src_rate > (request + delta))) + if ((parent_rate < (request - delta)) || + (parent_rate > (request + delta))) continue; regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, diff --git a/drivers/clk/spear/clk-aux-synth.c b/drivers/clk/spear/clk-aux-synth.c index bdfb4421c643..f271c350ef94 100644 --- a/drivers/clk/spear/clk-aux-synth.c +++ b/drivers/clk/spear/clk-aux-synth.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/clk/spear/clk-frac-synth.c b/drivers/clk/spear/clk-frac-synth.c index dffd4ce6c8b5..58d678b5b40a 100644 --- a/drivers/clk/spear/clk-frac-synth.c +++ b/drivers/clk/spear/clk-frac-synth.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/clk/spear/clk-gpt-synth.c b/drivers/clk/spear/clk-gpt-synth.c index 1afc18c4effc..1a722e99e76e 100644 --- a/drivers/clk/spear/clk-gpt-synth.c +++ b/drivers/clk/spear/clk-gpt-synth.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/clk/spear/clk-vco-pll.c b/drivers/clk/spear/clk-vco-pll.c index 1b9b65bca51e..5ebddc528145 100644 --- a/drivers/clk/spear/clk-vco-pll.c +++ b/drivers/clk/spear/clk-vco-pll.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/clk/spear/clk.c b/drivers/clk/spear/clk.c index 628b6d5ed3d9..157fe099ea6a 100644 --- a/drivers/clk/spear/clk.c +++ b/drivers/clk/spear/clk.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/clk/spear/clk.h b/drivers/clk/spear/clk.h index 931737677dfa..9834944f08b1 100644 --- a/drivers/clk/spear/clk.h +++ b/drivers/clk/spear/clk.h @@ -2,7 +2,7 @@ * Clock framework definitions for SPEAr platform * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/clk/spear/spear1310_clock.c b/drivers/clk/spear/spear1310_clock.c index 4daa5977793a..222ce108b41a 100644 --- a/drivers/clk/spear/spear1310_clock.c +++ b/drivers/clk/spear/spear1310_clock.c @@ -4,7 +4,7 @@ * SPEAr1310 machine clock framework source file * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/clk/spear/spear1340_clock.c b/drivers/clk/spear/spear1340_clock.c index 5a5c6648308d..973c9d3fbcf8 100644 --- a/drivers/clk/spear/spear1340_clock.c +++ b/drivers/clk/spear/spear1340_clock.c @@ -4,7 +4,7 @@ * SPEAr1340 machine clock framework source file * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/clk/spear/spear3xx_clock.c b/drivers/clk/spear/spear3xx_clock.c index bb5f387774e2..404a55edd613 100644 --- a/drivers/clk/spear/spear3xx_clock.c +++ b/drivers/clk/spear/spear3xx_clock.c @@ -2,7 +2,7 @@ * SPEAr3xx machines clock framework source file * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/clk/spear/spear6xx_clock.c b/drivers/clk/spear/spear6xx_clock.c index 4f649c9cb094..231061fa73a4 100644 --- a/drivers/clk/spear/spear6xx_clock.c +++ b/drivers/clk/spear/spear6xx_clock.c @@ -2,7 +2,7 @@ * SPEAr6xx machines clock framework source file * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c index 657ca14ba709..8dd8cce27361 100644 --- a/drivers/clk/st/clk-flexgen.c +++ b/drivers/clk/st/clk-flexgen.c @@ -190,7 +190,7 @@ static struct clk *clk_register_flexgen(const char *name, init.name = name; init.ops = &flexgen_ops; - init.flags = CLK_IS_BASIC | flexgen_flags; + init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE | flexgen_flags; init.parent_names = parent_names; init.num_parents = num_parents; @@ -303,6 +303,8 @@ static void __init st_of_flexgen_setup(struct device_node *np) if (!rlock) goto err; + spin_lock_init(rlock); + for (i = 0; i < clk_data->clk_num; i++) { struct clk *clk; const char *clk_name; diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c index e94197f04b0b..d9eb2e1d8471 100644 --- a/drivers/clk/st/clkgen-fsyn.c +++ b/drivers/clk/st/clkgen-fsyn.c @@ -340,7 +340,7 @@ static const struct clkgen_quadfs_data st_fs660c32_C_407 = { CLKGEN_FIELD(0x30c, 0xf, 20), CLKGEN_FIELD(0x310, 0xf, 20) }, .lockstatus_present = true, - .lock_status = CLKGEN_FIELD(0x2A0, 0x1, 24), + .lock_status = CLKGEN_FIELD(0x2f0, 0x1, 24), .powerup_polarity = 1, .standby_polarity = 1, .pll_ops = &st_quadfs_pll_c32_ops, @@ -489,7 +489,7 @@ static int quadfs_pll_is_enabled(struct clk_hw *hw) struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw); u32 npda = CLKGEN_READ(pll, npda); - return !!npda; + return pll->data->powerup_polarity ? !npda : !!npda; } static int clk_fs660c32_vco_get_rate(unsigned long input, struct stm_fs *fs, @@ -635,7 +635,7 @@ static struct clk * __init st_clk_register_quadfs_pll( init.name = name; init.ops = quadfs->pll_ops; - init.flags = CLK_IS_BASIC; + init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE; init.parent_names = &parent_name; init.num_parents = 1; @@ -774,7 +774,7 @@ static void quadfs_fsynth_disable(struct clk_hw *hw) if (fs->lock) spin_lock_irqsave(fs->lock, flags); - CLKGEN_WRITE(fs, nsb[fs->chan], !fs->data->standby_polarity); + CLKGEN_WRITE(fs, nsb[fs->chan], fs->data->standby_polarity); if (fs->lock) spin_unlock_irqrestore(fs->lock, flags); @@ -1082,10 +1082,6 @@ static const struct of_device_id quadfs_of_match[] = { .compatible = "st,stih407-quadfs660-D", .data = &st_fs660c32_D_407 }, - { - .compatible = "st,stih407-quadfs660-D", - .data = (void *)&st_fs660c32_D_407 - }, {} }; diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c index 4fbe6e099587..717c4a91a17b 100644 --- a/drivers/clk/st/clkgen-mux.c +++ b/drivers/clk/st/clkgen-mux.c @@ -237,7 +237,7 @@ static struct clk *clk_register_genamux(const char *name, init.name = name; init.ops = &clkgena_divmux_ops; - init.flags = CLK_IS_BASIC; + init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE; init.parent_names = parent_names; init.num_parents = num_parents; @@ -513,7 +513,8 @@ static void __init st_of_clkgena_prediv_setup(struct device_node *np) 0, &clk_name)) return; - clk = clk_register_divider_table(NULL, clk_name, parent_name, 0, + clk = clk_register_divider_table(NULL, clk_name, parent_name, + CLK_GET_RATE_NOCACHE, reg + data->offset, data->shift, 1, 0, data->table, NULL); if (IS_ERR(clk)) @@ -582,7 +583,7 @@ static struct clkgen_mux_data stih416_a9_mux_data = { }; static struct clkgen_mux_data stih407_a9_mux_data = { .offset = 0x1a4, - .shift = 1, + .shift = 0, .width = 2, }; @@ -786,7 +787,8 @@ static void __init st_of_clkgen_vcc_setup(struct device_node *np) &mux->hw, &clk_mux_ops, &div->hw, &clk_divider_ops, &gate->hw, &clk_gate_ops, - data->clk_flags); + data->clk_flags | + CLK_GET_RATE_NOCACHE); if (IS_ERR(clk)) { kfree(gate); kfree(div); diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c index 106532207213..72d1c27eaffa 100644 --- a/drivers/clk/st/clkgen-pll.c +++ b/drivers/clk/st/clkgen-pll.c @@ -406,7 +406,7 @@ static struct clk * __init clkgen_pll_register(const char *parent_name, init.name = clk_name; init.ops = pll_data->ops; - init.flags = CLK_IS_BASIC; + init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE; init.parent_names = &parent_name; init.num_parents = 1; diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 9a82f17d2d73..abf7b37faf73 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -1391,6 +1391,7 @@ static void __init sun6i_init_clocks(struct device_node *node) CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks); CLK_OF_DECLARE(sun6i_a31s_clk_init, "allwinner,sun6i-a31s", sun6i_init_clocks); CLK_OF_DECLARE(sun8i_a23_clk_init, "allwinner,sun8i-a23", sun6i_init_clocks); +CLK_OF_DECLARE(sun8i_a33_clk_init, "allwinner,sun8i-a33", sun6i_init_clocks); static void __init sun9i_init_clocks(struct device_node *node) { diff --git a/drivers/clocksource/timer-imx-gpt.c b/drivers/clocksource/timer-imx-gpt.c index 879c78423546..2d59038dec43 100644 --- a/drivers/clocksource/timer-imx-gpt.c +++ b/drivers/clocksource/timer-imx-gpt.c @@ -529,6 +529,7 @@ static void __init imx6dl_timer_init_dt(struct device_node *np) CLOCKSOURCE_OF_DECLARE(imx1_timer, "fsl,imx1-gpt", imx1_timer_init_dt); CLOCKSOURCE_OF_DECLARE(imx21_timer, "fsl,imx21-gpt", imx21_timer_init_dt); +CLOCKSOURCE_OF_DECLARE(imx27_timer, "fsl,imx27-gpt", imx21_timer_init_dt); CLOCKSOURCE_OF_DECLARE(imx31_timer, "fsl,imx31-gpt", imx31_timer_init_dt); CLOCKSOURCE_OF_DECLARE(imx25_timer, "fsl,imx25-gpt", imx31_timer_init_dt); CLOCKSOURCE_OF_DECLARE(imx50_timer, "fsl,imx50-gpt", imx31_timer_init_dt); diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index b612411655f9..7a3c30c4336f 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -169,6 +169,15 @@ struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy) } EXPORT_SYMBOL_GPL(get_governor_parent_kobj); +struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu) +{ + struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); + + return policy && !policy_is_inactive(policy) ? + policy->freq_table : NULL; +} +EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table); + static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall) { u64 idle_time; @@ -993,7 +1002,7 @@ static int cpufreq_add_dev_symlink(struct cpufreq_policy *policy) int ret = 0; /* Some related CPUs might not be present (physically hotplugged) */ - for_each_cpu_and(j, policy->related_cpus, cpu_present_mask) { + for_each_cpu(j, policy->real_cpus) { if (j == policy->kobj_cpu) continue; @@ -1010,7 +1019,7 @@ static void cpufreq_remove_dev_symlink(struct cpufreq_policy *policy) unsigned int j; /* Some related CPUs might not be present (physically hotplugged) */ - for_each_cpu_and(j, policy->related_cpus, cpu_present_mask) { + for_each_cpu(j, policy->real_cpus) { if (j == policy->kobj_cpu) continue; @@ -1132,6 +1141,7 @@ static struct cpufreq_policy *cpufreq_policy_restore(unsigned int cpu) down_write(&policy->rwsem); policy->cpu = cpu; + policy->governor = NULL; up_write(&policy->rwsem); } @@ -1153,11 +1163,14 @@ static struct cpufreq_policy *cpufreq_policy_alloc(struct device *dev) if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL)) goto err_free_cpumask; + if (!zalloc_cpumask_var(&policy->real_cpus, GFP_KERNEL)) + goto err_free_rcpumask; + ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &dev->kobj, "cpufreq"); if (ret) { pr_err("%s: failed to init policy->kobj: %d\n", __func__, ret); - goto err_free_rcpumask; + goto err_free_real_cpus; } INIT_LIST_HEAD(&policy->policy_list); @@ -1174,6 +1187,8 @@ static struct cpufreq_policy *cpufreq_policy_alloc(struct device *dev) return policy; +err_free_real_cpus: + free_cpumask_var(policy->real_cpus); err_free_rcpumask: free_cpumask_var(policy->related_cpus); err_free_cpumask: @@ -1224,6 +1239,7 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy, bool notify) write_unlock_irqrestore(&cpufreq_driver_lock, flags); cpufreq_policy_put_kobj(policy, notify); + free_cpumask_var(policy->real_cpus); free_cpumask_var(policy->related_cpus); free_cpumask_var(policy->cpus); kfree(policy); @@ -1248,14 +1264,17 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) pr_debug("adding CPU %u\n", cpu); - /* - * Only possible if 'cpu' wasn't physically present earlier and we are - * here from subsys_interface add callback. A hotplug notifier will - * follow and we will handle it like logical CPU hotplug then. For now, - * just create the sysfs link. - */ - if (cpu_is_offline(cpu)) - return add_cpu_dev_symlink(per_cpu(cpufreq_cpu_data, cpu), cpu); + if (cpu_is_offline(cpu)) { + /* + * Only possible if we are here from the subsys_interface add + * callback. A hotplug notifier will follow and we will handle + * it as CPU online then. For now, just create the sysfs link, + * unless there is no policy or the link is already present. + */ + policy = per_cpu(cpufreq_cpu_data, cpu); + return policy && !cpumask_test_and_set_cpu(cpu, policy->real_cpus) + ? add_cpu_dev_symlink(policy, cpu) : 0; + } if (!down_read_trylock(&cpufreq_rwsem)) return 0; @@ -1297,6 +1316,10 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) /* related cpus should atleast have policy->cpus */ cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus); + /* Remember which CPUs have been present at the policy creation time. */ + if (!recover_policy) + cpumask_and(policy->real_cpus, policy->cpus, cpu_present_mask); + /* * affected cpus must always be the one, which are online. We aren't * managing offline cpus here. @@ -1410,8 +1433,7 @@ nomem_out: return ret; } -static int __cpufreq_remove_dev_prepare(struct device *dev, - struct subsys_interface *sif) +static int __cpufreq_remove_dev_prepare(struct device *dev) { unsigned int cpu = dev->id; int ret = 0; @@ -1427,10 +1449,8 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, if (has_target()) { ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP); - if (ret) { + if (ret) pr_err("%s: Failed to stop governor\n", __func__); - return ret; - } } down_write(&policy->rwsem); @@ -1463,8 +1483,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, return ret; } -static int __cpufreq_remove_dev_finish(struct device *dev, - struct subsys_interface *sif) +static int __cpufreq_remove_dev_finish(struct device *dev) { unsigned int cpu = dev->id; int ret; @@ -1482,10 +1501,8 @@ static int __cpufreq_remove_dev_finish(struct device *dev, /* If cpu is last user of policy, free policy */ if (has_target()) { ret = __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); - if (ret) { + if (ret) pr_err("%s: Failed to exit governor\n", __func__); - return ret; - } } /* @@ -1496,10 +1513,6 @@ static int __cpufreq_remove_dev_finish(struct device *dev, if (cpufreq_driver->exit) cpufreq_driver->exit(policy); - /* Free the policy only if the driver is getting removed. */ - if (sif) - cpufreq_policy_free(policy, true); - return 0; } @@ -1511,42 +1524,41 @@ static int __cpufreq_remove_dev_finish(struct device *dev, static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) { unsigned int cpu = dev->id; - int ret; - - /* - * Only possible if 'cpu' is getting physically removed now. A hotplug - * notifier should have already been called and we just need to remove - * link or free policy here. - */ - if (cpu_is_offline(cpu)) { - struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); - struct cpumask mask; + struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); - if (!policy) - return 0; + if (!policy) + return 0; - cpumask_copy(&mask, policy->related_cpus); - cpumask_clear_cpu(cpu, &mask); + if (cpu_online(cpu)) { + __cpufreq_remove_dev_prepare(dev); + __cpufreq_remove_dev_finish(dev); + } - /* - * Free policy only if all policy->related_cpus are removed - * physically. - */ - if (cpumask_intersects(&mask, cpu_present_mask)) { - remove_cpu_dev_symlink(policy, cpu); - return 0; - } + cpumask_clear_cpu(cpu, policy->real_cpus); + if (cpumask_empty(policy->real_cpus)) { cpufreq_policy_free(policy, true); return 0; } - ret = __cpufreq_remove_dev_prepare(dev, sif); + if (cpu != policy->kobj_cpu) { + remove_cpu_dev_symlink(policy, cpu); + } else { + /* + * The CPU owning the policy object is going away. Move it to + * another suitable CPU. + */ + unsigned int new_cpu = cpumask_first(policy->real_cpus); + struct device *new_dev = get_cpu_device(new_cpu); - if (!ret) - ret = __cpufreq_remove_dev_finish(dev, sif); + dev_dbg(dev, "%s: Moving policy object to CPU%u\n", __func__, new_cpu); - return ret; + sysfs_remove_link(&new_dev->kobj, "cpufreq"); + policy->kobj_cpu = new_cpu; + WARN_ON(kobject_move(&policy->kobj, &new_dev->kobj)); + } + + return 0; } static void handle_update(struct work_struct *work) @@ -2385,11 +2397,11 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb, break; case CPU_DOWN_PREPARE: - __cpufreq_remove_dev_prepare(dev, NULL); + __cpufreq_remove_dev_prepare(dev); break; case CPU_POST_DEAD: - __cpufreq_remove_dev_finish(dev, NULL); + __cpufreq_remove_dev_finish(dev); break; case CPU_DOWN_FAILED: diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index df14766a8e06..dfbbf981ed56 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -297,15 +297,6 @@ int cpufreq_table_validate_and_show(struct cpufreq_policy *policy, } EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show); -struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu); - -struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu) -{ - struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu); - return policy ? policy->freq_table : NULL; -} -EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table); - MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>"); MODULE_DESCRIPTION("CPUfreq frequency table helpers"); MODULE_LICENSE("GPL"); diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 15ada47bb720..fcb929ec5304 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -681,6 +681,7 @@ static struct cpu_defaults knl_params = { .get_max = core_get_max_pstate, .get_min = core_get_min_pstate, .get_turbo = knl_get_turbo_pstate, + .get_scaling = core_get_scaling, .set = core_set_pstate, }, }; diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c index fc897babab55..cd593c1f66dc 100644 --- a/drivers/cpufreq/loongson2_cpufreq.c +++ b/drivers/cpufreq/loongson2_cpufreq.c @@ -3,7 +3,7 @@ * * The 2E revision of loongson processor not support this feature. * - * Copyright (C) 2006 - 2008 Lemote Inc. & Insititute of Computing Technology + * Copyright (C) 2006 - 2008 Lemote Inc. & Institute of Computing Technology * Author: Yanhua, yanh@lemote.com * * This file is subject to the terms and conditions of the GNU General Public @@ -20,7 +20,7 @@ #include <asm/clock.h> #include <asm/idle.h> -#include <asm/mach-loongson/loongson.h> +#include <asm/mach-loongson64/loongson.h> static uint nowait; diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index e8e2775c3821..48b7228563ad 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -112,7 +112,12 @@ int cpuidle_find_deepest_state(struct cpuidle_driver *drv, static void enter_freeze_proper(struct cpuidle_driver *drv, struct cpuidle_device *dev, int index) { - tick_freeze(); + /* + * trace_suspend_resume() called by tick_freeze() for the last CPU + * executing it contains RCU usage regarded as invalid in the idle + * context, so tell RCU about that. + */ + RCU_NONIDLE(tick_freeze()); /* * The state used here cannot be a "coupled" one, because the "coupled" * cpuidle mechanism enables interrupts and doing that with timekeeping @@ -122,7 +127,7 @@ static void enter_freeze_proper(struct cpuidle_driver *drv, WARN_ON(!irqs_disabled()); /* * timekeeping_resume() that will be called by tick_unfreeze() for the - * last CPU executing it calls functions containing RCU read-side + * first CPU executing it calls functions containing RCU read-side * critical sections, so tell RCU about that. */ RCU_NONIDLE(tick_unfreeze()); diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c index 7ba495f75370..402631a19a11 100644 --- a/drivers/crypto/ixp4xx_crypto.c +++ b/drivers/crypto/ixp4xx_crypto.c @@ -905,7 +905,6 @@ static int ablk_perform(struct ablkcipher_request *req, int encrypt) crypt->mode |= NPE_OP_NOT_IN_PLACE; /* This was never tested by Intel * for more than one dst buffer, I think. */ - BUG_ON(req->dst->length < nbytes); req_ctx->dst = NULL; if (!chainup_buffers(dev, req->dst, nbytes, &dst_hook, flags, DMA_FROM_DEVICE)) diff --git a/drivers/crypto/nx/nx-aes-ccm.c b/drivers/crypto/nx/nx-aes-ccm.c index 67f80813a06f..e4311ce0cd78 100644 --- a/drivers/crypto/nx/nx-aes-ccm.c +++ b/drivers/crypto/nx/nx-aes-ccm.c @@ -494,8 +494,9 @@ out: static int ccm4309_aes_nx_encrypt(struct aead_request *req) { struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm); + struct nx_gcm_rctx *rctx = aead_request_ctx(req); struct blkcipher_desc desc; - u8 *iv = nx_ctx->priv.ccm.iv; + u8 *iv = rctx->iv; iv[0] = 3; memcpy(iv + 1, nx_ctx->priv.ccm.nonce, 3); @@ -525,8 +526,9 @@ static int ccm_aes_nx_encrypt(struct aead_request *req) static int ccm4309_aes_nx_decrypt(struct aead_request *req) { struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm); + struct nx_gcm_rctx *rctx = aead_request_ctx(req); struct blkcipher_desc desc; - u8 *iv = nx_ctx->priv.ccm.iv; + u8 *iv = rctx->iv; iv[0] = 3; memcpy(iv + 1, nx_ctx->priv.ccm.nonce, 3); diff --git a/drivers/crypto/nx/nx-aes-ctr.c b/drivers/crypto/nx/nx-aes-ctr.c index 2617cd4d54dd..dd7e9f3f5b6b 100644 --- a/drivers/crypto/nx/nx-aes-ctr.c +++ b/drivers/crypto/nx/nx-aes-ctr.c @@ -72,7 +72,7 @@ static int ctr3686_aes_nx_set_key(struct crypto_tfm *tfm, if (key_len < CTR_RFC3686_NONCE_SIZE) return -EINVAL; - memcpy(nx_ctx->priv.ctr.iv, + memcpy(nx_ctx->priv.ctr.nonce, in_key + key_len - CTR_RFC3686_NONCE_SIZE, CTR_RFC3686_NONCE_SIZE); @@ -131,14 +131,15 @@ static int ctr3686_aes_nx_crypt(struct blkcipher_desc *desc, unsigned int nbytes) { struct nx_crypto_ctx *nx_ctx = crypto_blkcipher_ctx(desc->tfm); - u8 *iv = nx_ctx->priv.ctr.iv; + u8 iv[16]; + memcpy(iv, nx_ctx->priv.ctr.nonce, CTR_RFC3686_IV_SIZE); memcpy(iv + CTR_RFC3686_NONCE_SIZE, desc->info, CTR_RFC3686_IV_SIZE); iv[12] = iv[13] = iv[14] = 0; iv[15] = 1; - desc->info = nx_ctx->priv.ctr.iv; + desc->info = iv; return ctr_aes_nx_crypt(desc, dst, src, nbytes); } diff --git a/drivers/crypto/nx/nx-aes-gcm.c b/drivers/crypto/nx/nx-aes-gcm.c index 08ac6d48688c..92c993f08213 100644 --- a/drivers/crypto/nx/nx-aes-gcm.c +++ b/drivers/crypto/nx/nx-aes-gcm.c @@ -317,6 +317,7 @@ out: static int gcm_aes_nx_crypt(struct aead_request *req, int enc) { struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm); + struct nx_gcm_rctx *rctx = aead_request_ctx(req); struct nx_csbcpb *csbcpb = nx_ctx->csbcpb; struct blkcipher_desc desc; unsigned int nbytes = req->cryptlen; @@ -326,7 +327,7 @@ static int gcm_aes_nx_crypt(struct aead_request *req, int enc) spin_lock_irqsave(&nx_ctx->lock, irq_flags); - desc.info = nx_ctx->priv.gcm.iv; + desc.info = rctx->iv; /* initialize the counter */ *(u32 *)(desc.info + NX_GCM_CTR_OFFSET) = 1; @@ -424,8 +425,8 @@ out: static int gcm_aes_nx_encrypt(struct aead_request *req) { - struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm); - char *iv = nx_ctx->priv.gcm.iv; + struct nx_gcm_rctx *rctx = aead_request_ctx(req); + char *iv = rctx->iv; memcpy(iv, req->iv, 12); @@ -434,8 +435,8 @@ static int gcm_aes_nx_encrypt(struct aead_request *req) static int gcm_aes_nx_decrypt(struct aead_request *req) { - struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm); - char *iv = nx_ctx->priv.gcm.iv; + struct nx_gcm_rctx *rctx = aead_request_ctx(req); + char *iv = rctx->iv; memcpy(iv, req->iv, 12); @@ -445,7 +446,8 @@ static int gcm_aes_nx_decrypt(struct aead_request *req) static int gcm4106_aes_nx_encrypt(struct aead_request *req) { struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm); - char *iv = nx_ctx->priv.gcm.iv; + struct nx_gcm_rctx *rctx = aead_request_ctx(req); + char *iv = rctx->iv; char *nonce = nx_ctx->priv.gcm.nonce; memcpy(iv, nonce, NX_GCM4106_NONCE_LEN); @@ -457,7 +459,8 @@ static int gcm4106_aes_nx_encrypt(struct aead_request *req) static int gcm4106_aes_nx_decrypt(struct aead_request *req) { struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm); - char *iv = nx_ctx->priv.gcm.iv; + struct nx_gcm_rctx *rctx = aead_request_ctx(req); + char *iv = rctx->iv; char *nonce = nx_ctx->priv.gcm.nonce; memcpy(iv, nonce, NX_GCM4106_NONCE_LEN); diff --git a/drivers/crypto/nx/nx-aes-xcbc.c b/drivers/crypto/nx/nx-aes-xcbc.c index 8c2faffab4a3..c2f7d4befb55 100644 --- a/drivers/crypto/nx/nx-aes-xcbc.c +++ b/drivers/crypto/nx/nx-aes-xcbc.c @@ -42,6 +42,7 @@ static int nx_xcbc_set_key(struct crypto_shash *desc, unsigned int key_len) { struct nx_crypto_ctx *nx_ctx = crypto_shash_ctx(desc); + struct nx_csbcpb *csbcpb = nx_ctx->csbcpb; switch (key_len) { case AES_KEYSIZE_128: @@ -51,7 +52,7 @@ static int nx_xcbc_set_key(struct crypto_shash *desc, return -EINVAL; } - memcpy(nx_ctx->priv.xcbc.key, in_key, key_len); + memcpy(csbcpb->cpb.aes_xcbc.key, in_key, key_len); return 0; } @@ -148,32 +149,29 @@ out: return rc; } -static int nx_xcbc_init(struct shash_desc *desc) +static int nx_crypto_ctx_aes_xcbc_init2(struct crypto_tfm *tfm) { - struct xcbc_state *sctx = shash_desc_ctx(desc); - struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base); + struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm); struct nx_csbcpb *csbcpb = nx_ctx->csbcpb; - struct nx_sg *out_sg; - int len; + int err; - nx_ctx_init(nx_ctx, HCOP_FC_AES); + err = nx_crypto_ctx_aes_xcbc_init(tfm); + if (err) + return err; - memset(sctx, 0, sizeof *sctx); + nx_ctx_init(nx_ctx, HCOP_FC_AES); NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128); csbcpb->cpb.hdr.mode = NX_MODE_AES_XCBC_MAC; - memcpy(csbcpb->cpb.aes_xcbc.key, nx_ctx->priv.xcbc.key, AES_BLOCK_SIZE); - memset(nx_ctx->priv.xcbc.key, 0, sizeof *nx_ctx->priv.xcbc.key); - - len = AES_BLOCK_SIZE; - out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state, - &len, nx_ctx->ap->sglen); + return 0; +} - if (len != AES_BLOCK_SIZE) - return -EINVAL; +static int nx_xcbc_init(struct shash_desc *desc) +{ + struct xcbc_state *sctx = shash_desc_ctx(desc); - nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg); + memset(sctx, 0, sizeof *sctx); return 0; } @@ -186,6 +184,7 @@ static int nx_xcbc_update(struct shash_desc *desc, struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base); struct nx_csbcpb *csbcpb = nx_ctx->csbcpb; struct nx_sg *in_sg; + struct nx_sg *out_sg; u32 to_process = 0, leftover, total; unsigned int max_sg_len; unsigned long irq_flags; @@ -213,6 +212,17 @@ static int nx_xcbc_update(struct shash_desc *desc, max_sg_len = min_t(u64, max_sg_len, nx_ctx->ap->databytelen/NX_PAGE_SIZE); + data_len = AES_BLOCK_SIZE; + out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state, + &len, nx_ctx->ap->sglen); + + if (data_len != AES_BLOCK_SIZE) { + rc = -EINVAL; + goto out; + } + + nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg); + do { to_process = total - to_process; to_process = to_process & ~(AES_BLOCK_SIZE - 1); @@ -235,8 +245,10 @@ static int nx_xcbc_update(struct shash_desc *desc, (u8 *) sctx->buffer, &data_len, max_sg_len); - if (data_len != sctx->count) - return -EINVAL; + if (data_len != sctx->count) { + rc = -EINVAL; + goto out; + } } data_len = to_process - sctx->count; @@ -245,8 +257,10 @@ static int nx_xcbc_update(struct shash_desc *desc, &data_len, max_sg_len); - if (data_len != to_process - sctx->count) - return -EINVAL; + if (data_len != to_process - sctx->count) { + rc = -EINVAL; + goto out; + } nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg); @@ -325,15 +339,19 @@ static int nx_xcbc_final(struct shash_desc *desc, u8 *out) in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *)sctx->buffer, &len, nx_ctx->ap->sglen); - if (len != sctx->count) - return -EINVAL; + if (len != sctx->count) { + rc = -EINVAL; + goto out; + } len = AES_BLOCK_SIZE; out_sg = nx_build_sg_list(nx_ctx->out_sg, out, &len, nx_ctx->ap->sglen); - if (len != AES_BLOCK_SIZE) - return -EINVAL; + if (len != AES_BLOCK_SIZE) { + rc = -EINVAL; + goto out; + } nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg); nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg); @@ -372,7 +390,7 @@ struct shash_alg nx_shash_aes_xcbc_alg = { .cra_blocksize = AES_BLOCK_SIZE, .cra_module = THIS_MODULE, .cra_ctxsize = sizeof(struct nx_crypto_ctx), - .cra_init = nx_crypto_ctx_aes_xcbc_init, + .cra_init = nx_crypto_ctx_aes_xcbc_init2, .cra_exit = nx_crypto_ctx_exit, } }; diff --git a/drivers/crypto/nx/nx-sha256.c b/drivers/crypto/nx/nx-sha256.c index 4e91bdb83c59..08f8d5cd6334 100644 --- a/drivers/crypto/nx/nx-sha256.c +++ b/drivers/crypto/nx/nx-sha256.c @@ -29,34 +29,28 @@ #include "nx.h" -static int nx_sha256_init(struct shash_desc *desc) +static int nx_crypto_ctx_sha256_init(struct crypto_tfm *tfm) { - struct sha256_state *sctx = shash_desc_ctx(desc); - struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base); - struct nx_sg *out_sg; - int len; - u32 max_sg_len; + struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm); + int err; - nx_ctx_init(nx_ctx, HCOP_FC_SHA); + err = nx_crypto_ctx_sha_init(tfm); + if (err) + return err; - memset(sctx, 0, sizeof *sctx); + nx_ctx_init(nx_ctx, HCOP_FC_SHA); nx_ctx->ap = &nx_ctx->props[NX_PROPS_SHA256]; NX_CPB_SET_DIGEST_SIZE(nx_ctx->csbcpb, NX_DS_SHA256); - max_sg_len = min_t(u64, nx_ctx->ap->sglen, - nx_driver.of.max_sg_len/sizeof(struct nx_sg)); - max_sg_len = min_t(u64, max_sg_len, - nx_ctx->ap->databytelen/NX_PAGE_SIZE); + return 0; +} - len = SHA256_DIGEST_SIZE; - out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state, - &len, max_sg_len); - nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg); +static int nx_sha256_init(struct shash_desc *desc) { + struct sha256_state *sctx = shash_desc_ctx(desc); - if (len != SHA256_DIGEST_SIZE) - return -EINVAL; + memset(sctx, 0, sizeof *sctx); sctx->state[0] = __cpu_to_be32(SHA256_H0); sctx->state[1] = __cpu_to_be32(SHA256_H1); @@ -78,6 +72,7 @@ static int nx_sha256_update(struct shash_desc *desc, const u8 *data, struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base); struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb; struct nx_sg *in_sg; + struct nx_sg *out_sg; u64 to_process = 0, leftover, total; unsigned long irq_flags; int rc = 0; @@ -108,6 +103,16 @@ static int nx_sha256_update(struct shash_desc *desc, const u8 *data, max_sg_len = min_t(u64, max_sg_len, nx_ctx->ap->databytelen/NX_PAGE_SIZE); + data_len = SHA256_DIGEST_SIZE; + out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state, + &data_len, max_sg_len); + nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg); + + if (data_len != SHA256_DIGEST_SIZE) { + rc = -EINVAL; + goto out; + } + do { /* * to_process: the SHA256_BLOCK_SIZE data chunk to process in @@ -282,7 +287,7 @@ struct shash_alg nx_shash_sha256_alg = { .cra_blocksize = SHA256_BLOCK_SIZE, .cra_module = THIS_MODULE, .cra_ctxsize = sizeof(struct nx_crypto_ctx), - .cra_init = nx_crypto_ctx_sha_init, + .cra_init = nx_crypto_ctx_sha256_init, .cra_exit = nx_crypto_ctx_exit, } }; diff --git a/drivers/crypto/nx/nx-sha512.c b/drivers/crypto/nx/nx-sha512.c index e6a58d2ee628..aff0fe58eac0 100644 --- a/drivers/crypto/nx/nx-sha512.c +++ b/drivers/crypto/nx/nx-sha512.c @@ -28,34 +28,29 @@ #include "nx.h" -static int nx_sha512_init(struct shash_desc *desc) +static int nx_crypto_ctx_sha512_init(struct crypto_tfm *tfm) { - struct sha512_state *sctx = shash_desc_ctx(desc); - struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base); - struct nx_sg *out_sg; - int len; - u32 max_sg_len; + struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm); + int err; - nx_ctx_init(nx_ctx, HCOP_FC_SHA); + err = nx_crypto_ctx_sha_init(tfm); + if (err) + return err; - memset(sctx, 0, sizeof *sctx); + nx_ctx_init(nx_ctx, HCOP_FC_SHA); nx_ctx->ap = &nx_ctx->props[NX_PROPS_SHA512]; NX_CPB_SET_DIGEST_SIZE(nx_ctx->csbcpb, NX_DS_SHA512); - max_sg_len = min_t(u64, nx_ctx->ap->sglen, - nx_driver.of.max_sg_len/sizeof(struct nx_sg)); - max_sg_len = min_t(u64, max_sg_len, - nx_ctx->ap->databytelen/NX_PAGE_SIZE); + return 0; +} - len = SHA512_DIGEST_SIZE; - out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state, - &len, max_sg_len); - nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg); +static int nx_sha512_init(struct shash_desc *desc) +{ + struct sha512_state *sctx = shash_desc_ctx(desc); - if (len != SHA512_DIGEST_SIZE) - return -EINVAL; + memset(sctx, 0, sizeof *sctx); sctx->state[0] = __cpu_to_be64(SHA512_H0); sctx->state[1] = __cpu_to_be64(SHA512_H1); @@ -77,6 +72,7 @@ static int nx_sha512_update(struct shash_desc *desc, const u8 *data, struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base); struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb; struct nx_sg *in_sg; + struct nx_sg *out_sg; u64 to_process, leftover = 0, total; unsigned long irq_flags; int rc = 0; @@ -107,6 +103,16 @@ static int nx_sha512_update(struct shash_desc *desc, const u8 *data, max_sg_len = min_t(u64, max_sg_len, nx_ctx->ap->databytelen/NX_PAGE_SIZE); + data_len = SHA512_DIGEST_SIZE; + out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state, + &data_len, max_sg_len); + nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg); + + if (data_len != SHA512_DIGEST_SIZE) { + rc = -EINVAL; + goto out; + } + do { /* * to_process: the SHA512_BLOCK_SIZE data chunk to process in @@ -288,7 +294,7 @@ struct shash_alg nx_shash_sha512_alg = { .cra_blocksize = SHA512_BLOCK_SIZE, .cra_module = THIS_MODULE, .cra_ctxsize = sizeof(struct nx_crypto_ctx), - .cra_init = nx_crypto_ctx_sha_init, + .cra_init = nx_crypto_ctx_sha512_init, .cra_exit = nx_crypto_ctx_exit, } }; diff --git a/drivers/crypto/nx/nx.c b/drivers/crypto/nx/nx.c index f6198f29a4a8..436971343ff7 100644 --- a/drivers/crypto/nx/nx.c +++ b/drivers/crypto/nx/nx.c @@ -713,12 +713,15 @@ static int nx_crypto_ctx_init(struct nx_crypto_ctx *nx_ctx, u32 fc, u32 mode) /* entry points from the crypto tfm initializers */ int nx_crypto_ctx_aes_ccm_init(struct crypto_tfm *tfm) { + crypto_aead_set_reqsize(__crypto_aead_cast(tfm), + sizeof(struct nx_ccm_rctx)); return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES, NX_MODE_AES_CCM); } int nx_crypto_ctx_aes_gcm_init(struct crypto_aead *tfm) { + crypto_aead_set_reqsize(tfm, sizeof(struct nx_gcm_rctx)); return nx_crypto_ctx_init(crypto_aead_ctx(tfm), NX_FC_AES, NX_MODE_AES_GCM); } diff --git a/drivers/crypto/nx/nx.h b/drivers/crypto/nx/nx.h index de3ea8738146..cdff03a42ae7 100644 --- a/drivers/crypto/nx/nx.h +++ b/drivers/crypto/nx/nx.h @@ -2,6 +2,8 @@ #ifndef __NX_H__ #define __NX_H__ +#include <crypto/ctr.h> + #define NX_NAME "nx-crypto" #define NX_STRING "IBM Power7+ Nest Accelerator Crypto Driver" #define NX_VERSION "1.0" @@ -91,8 +93,11 @@ struct nx_crypto_driver { #define NX_GCM4106_NONCE_LEN (4) #define NX_GCM_CTR_OFFSET (12) -struct nx_gcm_priv { +struct nx_gcm_rctx { u8 iv[16]; +}; + +struct nx_gcm_priv { u8 iauth_tag[16]; u8 nonce[NX_GCM4106_NONCE_LEN]; }; @@ -100,8 +105,11 @@ struct nx_gcm_priv { #define NX_CCM_AES_KEY_LEN (16) #define NX_CCM4309_AES_KEY_LEN (19) #define NX_CCM4309_NONCE_LEN (3) -struct nx_ccm_priv { +struct nx_ccm_rctx { u8 iv[16]; +}; + +struct nx_ccm_priv { u8 b0[16]; u8 iauth_tag[16]; u8 oauth_tag[16]; @@ -113,7 +121,7 @@ struct nx_xcbc_priv { }; struct nx_ctr_priv { - u8 iv[16]; + u8 nonce[CTR_RFC3686_NONCE_SIZE]; }; struct nx_crypto_ctx { diff --git a/drivers/crypto/omap-des.c b/drivers/crypto/omap-des.c index 46307098f8ba..0a70e46d5416 100644 --- a/drivers/crypto/omap-des.c +++ b/drivers/crypto/omap-des.c @@ -536,9 +536,6 @@ static int omap_des_crypt_dma_stop(struct omap_des_dev *dd) dmaengine_terminate_all(dd->dma_lch_in); dmaengine_terminate_all(dd->dma_lch_out); - dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE); - dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len, DMA_FROM_DEVICE); - return err; } diff --git a/drivers/crypto/qat/qat_common/qat_algs.c b/drivers/crypto/qat/qat_common/qat_algs.c index 067402c7c2a9..df427c0e9e7b 100644 --- a/drivers/crypto/qat/qat_common/qat_algs.c +++ b/drivers/crypto/qat/qat_common/qat_algs.c @@ -73,7 +73,8 @@ ICP_QAT_HW_CIPHER_KEY_CONVERT, \ ICP_QAT_HW_CIPHER_DECRYPT) -static atomic_t active_dev; +static DEFINE_MUTEX(algs_lock); +static unsigned int active_devs; struct qat_alg_buf { uint32_t len; @@ -1280,7 +1281,10 @@ static struct crypto_alg qat_algs[] = { { int qat_algs_register(void) { - if (atomic_add_return(1, &active_dev) == 1) { + int ret = 0; + + mutex_lock(&algs_lock); + if (++active_devs == 1) { int i; for (i = 0; i < ARRAY_SIZE(qat_algs); i++) @@ -1289,21 +1293,25 @@ int qat_algs_register(void) CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC : CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC; - return crypto_register_algs(qat_algs, ARRAY_SIZE(qat_algs)); + ret = crypto_register_algs(qat_algs, ARRAY_SIZE(qat_algs)); } - return 0; + mutex_unlock(&algs_lock); + return ret; } int qat_algs_unregister(void) { - if (atomic_sub_return(1, &active_dev) == 0) - return crypto_unregister_algs(qat_algs, ARRAY_SIZE(qat_algs)); - return 0; + int ret = 0; + + mutex_lock(&algs_lock); + if (--active_devs == 0) + ret = crypto_unregister_algs(qat_algs, ARRAY_SIZE(qat_algs)); + mutex_unlock(&algs_lock); + return ret; } int qat_algs_init(void) { - atomic_set(&active_dev, 0); crypto_get_default_rng(); return 0; } diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 59892126d175..d3629b7482dd 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -48,6 +48,8 @@ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |\ BIT(DMA_SLAVE_BUSWIDTH_4_BYTES)) +#define ATC_MAX_DSCR_TRIALS 10 + /* * Initial number of descriptors to allocate for each channel. This could * be increased during dma usage. @@ -285,28 +287,19 @@ static struct at_desc *atc_get_desc_by_cookie(struct at_dma_chan *atchan, * * @current_len: the number of bytes left before reading CTRLA * @ctrla: the value of CTRLA - * @desc: the descriptor containing the transfer width */ -static inline int atc_calc_bytes_left(int current_len, u32 ctrla, - struct at_desc *desc) +static inline int atc_calc_bytes_left(int current_len, u32 ctrla) { - return current_len - ((ctrla & ATC_BTSIZE_MAX) << desc->tx_width); -} + u32 btsize = (ctrla & ATC_BTSIZE_MAX); + u32 src_width = ATC_REG_TO_SRC_WIDTH(ctrla); -/** - * atc_calc_bytes_left_from_reg - calculates the number of bytes left according - * to the current value of CTRLA. - * - * @current_len: the number of bytes left before reading CTRLA - * @atchan: the channel to read CTRLA for - * @desc: the descriptor containing the transfer width - */ -static inline int atc_calc_bytes_left_from_reg(int current_len, - struct at_dma_chan *atchan, struct at_desc *desc) -{ - u32 ctrla = channel_readl(atchan, CTRLA); - - return atc_calc_bytes_left(current_len, ctrla, desc); + /* + * According to the datasheet, when reading the Control A Register + * (ctrla), the Buffer Transfer Size (btsize) bitfield refers to the + * number of transfers completed on the Source Interface. + * So btsize is always a number of source width transfers. + */ + return current_len - (btsize << src_width); } /** @@ -320,7 +313,7 @@ static int atc_get_bytes_left(struct dma_chan *chan, dma_cookie_t cookie) struct at_desc *desc_first = atc_first_active(atchan); struct at_desc *desc; int ret; - u32 ctrla, dscr; + u32 ctrla, dscr, trials; /* * If the cookie doesn't match to the currently running transfer then @@ -346,15 +339,82 @@ static int atc_get_bytes_left(struct dma_chan *chan, dma_cookie_t cookie) * the channel's DSCR register and compare it against the value * of the hardware linked list structure of each child * descriptor. + * + * The CTRLA register provides us with the amount of data + * already read from the source for the current child + * descriptor. So we can compute a more accurate residue by also + * removing the number of bytes corresponding to this amount of + * data. + * + * However, the DSCR and CTRLA registers cannot be read both + * atomically. Hence a race condition may occur: the first read + * register may refer to one child descriptor whereas the second + * read may refer to a later child descriptor in the list + * because of the DMA transfer progression inbetween the two + * reads. + * + * One solution could have been to pause the DMA transfer, read + * the DSCR and CTRLA then resume the DMA transfer. Nonetheless, + * this approach presents some drawbacks: + * - If the DMA transfer is paused, RX overruns or TX underruns + * are more likey to occur depending on the system latency. + * Taking the USART driver as an example, it uses a cyclic DMA + * transfer to read data from the Receive Holding Register + * (RHR) to avoid RX overruns since the RHR is not protected + * by any FIFO on most Atmel SoCs. So pausing the DMA transfer + * to compute the residue would break the USART driver design. + * - The atc_pause() function masks interrupts but we'd rather + * avoid to do so for system latency purpose. + * + * Then we'd rather use another solution: the DSCR is read a + * first time, the CTRLA is read in turn, next the DSCR is read + * a second time. If the two consecutive read values of the DSCR + * are the same then we assume both refers to the very same + * child descriptor as well as the CTRLA value read inbetween + * does. For cyclic tranfers, the assumption is that a full loop + * is "not so fast". + * If the two DSCR values are different, we read again the CTRLA + * then the DSCR till two consecutive read values from DSCR are + * equal or till the maxium trials is reach. + * This algorithm is very unlikely not to find a stable value for + * DSCR. */ - ctrla = channel_readl(atchan, CTRLA); - rmb(); /* ensure CTRLA is read before DSCR */ dscr = channel_readl(atchan, DSCR); + rmb(); /* ensure DSCR is read before CTRLA */ + ctrla = channel_readl(atchan, CTRLA); + for (trials = 0; trials < ATC_MAX_DSCR_TRIALS; ++trials) { + u32 new_dscr; + + rmb(); /* ensure DSCR is read after CTRLA */ + new_dscr = channel_readl(atchan, DSCR); + + /* + * If the DSCR register value has not changed inside the + * DMA controller since the previous read, we assume + * that both the dscr and ctrla values refers to the + * very same descriptor. + */ + if (likely(new_dscr == dscr)) + break; + + /* + * DSCR has changed inside the DMA controller, so the + * previouly read value of CTRLA may refer to an already + * processed descriptor hence could be outdated. + * We need to update ctrla to match the current + * descriptor. + */ + dscr = new_dscr; + rmb(); /* ensure DSCR is read before CTRLA */ + ctrla = channel_readl(atchan, CTRLA); + } + if (unlikely(trials >= ATC_MAX_DSCR_TRIALS)) + return -ETIMEDOUT; /* for the first descriptor we can be more accurate */ if (desc_first->lli.dscr == dscr) - return atc_calc_bytes_left(ret, ctrla, desc_first); + return atc_calc_bytes_left(ret, ctrla); ret -= desc_first->len; list_for_each_entry(desc, &desc_first->tx_list, desc_node) { @@ -365,16 +425,14 @@ static int atc_get_bytes_left(struct dma_chan *chan, dma_cookie_t cookie) } /* - * For the last descriptor in the chain we can calculate + * For the current descriptor in the chain we can calculate * the remaining bytes using the channel's register. - * Note that the transfer width of the first and last - * descriptor may differ. */ - if (!desc->lli.dscr) - ret = atc_calc_bytes_left_from_reg(ret, atchan, desc); + ret = atc_calc_bytes_left(ret, ctrla); } else { /* single transfer */ - ret = atc_calc_bytes_left_from_reg(ret, atchan, desc_first); + ctrla = channel_readl(atchan, CTRLA); + ret = atc_calc_bytes_left(ret, ctrla); } return ret; @@ -726,7 +784,6 @@ atc_prep_dma_interleaved(struct dma_chan *chan, desc->txd.cookie = -EBUSY; desc->total_len = desc->len = len; - desc->tx_width = dwidth; /* set end-of-link to the last link descriptor of list*/ set_desc_eol(desc); @@ -804,10 +861,6 @@ atc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, first->txd.cookie = -EBUSY; first->total_len = len; - /* set transfer width for the calculation of the residue */ - first->tx_width = src_width; - prev->tx_width = src_width; - /* set end-of-link to the last link descriptor of list*/ set_desc_eol(desc); @@ -956,10 +1009,6 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, first->txd.cookie = -EBUSY; first->total_len = total_len; - /* set transfer width for the calculation of the residue */ - first->tx_width = reg_width; - prev->tx_width = reg_width; - /* first link descriptor of list is responsible of flags */ first->txd.flags = flags; /* client is in control of this ack */ @@ -1077,12 +1126,6 @@ atc_prep_dma_sg(struct dma_chan *chan, desc->txd.cookie = 0; desc->len = len; - /* - * Although we only need the transfer width for the first and - * the last descriptor, its easier to set it to all descriptors. - */ - desc->tx_width = src_width; - atc_desc_chain(&first, &prev, desc); /* update the lengths and addresses for the next loop cycle */ @@ -1256,7 +1299,6 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, /* First descriptor of the chain embedds additional information */ first->txd.cookie = -EBUSY; first->total_len = buf_len; - first->tx_width = reg_width; return &first->txd; diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h index bc8d5ebedd19..7f5a08230f76 100644 --- a/drivers/dma/at_hdmac_regs.h +++ b/drivers/dma/at_hdmac_regs.h @@ -112,6 +112,7 @@ #define ATC_SRC_WIDTH_BYTE (0x0 << 24) #define ATC_SRC_WIDTH_HALFWORD (0x1 << 24) #define ATC_SRC_WIDTH_WORD (0x2 << 24) +#define ATC_REG_TO_SRC_WIDTH(r) (((r) >> 24) & 0x3) #define ATC_DST_WIDTH_MASK (0x3 << 28) /* Destination Single Transfer Size */ #define ATC_DST_WIDTH(x) ((x) << 28) #define ATC_DST_WIDTH_BYTE (0x0 << 28) @@ -182,7 +183,6 @@ struct at_lli { * @txd: support for the async_tx api * @desc_node: node on the channed descriptors list * @len: descriptor byte count - * @tx_width: transfer width * @total_len: total transaction byte count */ struct at_desc { @@ -194,7 +194,6 @@ struct at_desc { struct dma_async_tx_descriptor txd; struct list_head desc_node; size_t len; - u32 tx_width; size_t total_len; /* Interleaved data */ diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c index cf1213de7865..40afa2a16cfc 100644 --- a/drivers/dma/at_xdmac.c +++ b/drivers/dma/at_xdmac.c @@ -359,18 +359,19 @@ static void at_xdmac_start_xfer(struct at_xdmac_chan *atchan, * descriptor view 2 since some fields of the configuration register * depend on transfer size and src/dest addresses. */ - if (at_xdmac_chan_is_cyclic(atchan)) { + if (at_xdmac_chan_is_cyclic(atchan)) reg = AT_XDMAC_CNDC_NDVIEW_NDV1; - at_xdmac_chan_write(atchan, AT_XDMAC_CC, first->lld.mbr_cfg); - } else if (first->lld.mbr_ubc & AT_XDMAC_MBR_UBC_NDV3) { + else if (first->lld.mbr_ubc & AT_XDMAC_MBR_UBC_NDV3) reg = AT_XDMAC_CNDC_NDVIEW_NDV3; - } else { - /* - * No need to write AT_XDMAC_CC reg, it will be done when the - * descriptor is fecthed. - */ + else reg = AT_XDMAC_CNDC_NDVIEW_NDV2; - } + /* + * Even if the register will be updated from the configuration in the + * descriptor when using view 2 or higher, the PROT bit won't be set + * properly. This bit can be modified only by using the channel + * configuration register. + */ + at_xdmac_chan_write(atchan, AT_XDMAC_CC, first->lld.mbr_cfg); reg |= AT_XDMAC_CNDC_NDDUP | AT_XDMAC_CNDC_NDSUP @@ -681,15 +682,16 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, desc->lld.mbr_sa = mem; desc->lld.mbr_da = atchan->sconfig.dst_addr; } - desc->lld.mbr_cfg = atchan->cfg; - dwidth = at_xdmac_get_dwidth(desc->lld.mbr_cfg); + dwidth = at_xdmac_get_dwidth(atchan->cfg); fixed_dwidth = IS_ALIGNED(len, 1 << dwidth) - ? at_xdmac_get_dwidth(desc->lld.mbr_cfg) + ? dwidth : AT_XDMAC_CC_DWIDTH_BYTE; desc->lld.mbr_ubc = AT_XDMAC_MBR_UBC_NDV2 /* next descriptor view */ | AT_XDMAC_MBR_UBC_NDEN /* next descriptor dst parameter update */ | AT_XDMAC_MBR_UBC_NSEN /* next descriptor src parameter update */ | (len >> fixed_dwidth); /* microblock length */ + desc->lld.mbr_cfg = (atchan->cfg & ~AT_XDMAC_CC_DWIDTH_MASK) | + AT_XDMAC_CC_DWIDTH(fixed_dwidth); dev_dbg(chan2dev(chan), "%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x\n", __func__, &desc->lld.mbr_sa, &desc->lld.mbr_da, desc->lld.mbr_ubc); diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index 1022c2e1a2b0..cf1c87fa1edd 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -1746,4 +1746,4 @@ EXPORT_SYMBOL_GPL(dw_dma_enable); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller core driver"); MODULE_AUTHOR("Haavard Skinnemoen (Atmel)"); -MODULE_AUTHOR("Viresh Kumar <viresh.linux@gmail.com>"); +MODULE_AUTHOR("Viresh Kumar <vireshk@kernel.org>"); diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index fbaf1ead2597..f1325f62563e 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -162,10 +162,11 @@ static void mv_chan_set_mode(struct mv_xor_chan *chan, config &= ~0x7; config |= op_mode; - if (IS_ENABLED(__BIG_ENDIAN)) - config |= XOR_DESCRIPTOR_SWAP; - else - config &= ~XOR_DESCRIPTOR_SWAP; +#if defined(__BIG_ENDIAN) + config |= XOR_DESCRIPTOR_SWAP; +#else + config &= ~XOR_DESCRIPTOR_SWAP; +#endif writel_relaxed(config, XOR_CONFIG(chan)); chan->current_type = type; diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index f513f77b1d85..ecab4ea059b4 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -2328,7 +2328,7 @@ static dma_cookie_t pl330_tx_submit(struct dma_async_tx_descriptor *tx) desc->txd.callback = last->txd.callback; desc->txd.callback_param = last->txd.callback_param; } - last->last = false; + desc->last = false; dma_cookie_assign(&desc->txd); @@ -2623,6 +2623,7 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst, desc->rqcfg.brst_len = 1; desc->rqcfg.brst_len = get_burst_len(desc, len); + desc->bytes_requested = len; desc->txd.flags = flags; diff --git a/drivers/dma/virt-dma.c b/drivers/dma/virt-dma.c index 7d2c17d8d30f..6f80432a3f0a 100644 --- a/drivers/dma/virt-dma.c +++ b/drivers/dma/virt-dma.c @@ -29,7 +29,7 @@ dma_cookie_t vchan_tx_submit(struct dma_async_tx_descriptor *tx) spin_lock_irqsave(&vc->lock, flags); cookie = dma_cookie_assign(tx); - list_move_tail(&vd->node, &vc->desc_submitted); + list_add_tail(&vd->node, &vc->desc_submitted); spin_unlock_irqrestore(&vc->lock, flags); dev_dbg(vc->chan.device->dev, "vchan %p: txd %p[%x]: submitted\n", @@ -83,10 +83,8 @@ static void vchan_complete(unsigned long arg) cb_data = vd->tx.callback_param; list_del(&vd->node); - if (async_tx_test_ack(&vd->tx)) - list_add(&vd->node, &vc->desc_allocated); - else - vc->desc_free(vd); + + vc->desc_free(vd); if (cb) cb(cb_data); @@ -98,13 +96,9 @@ void vchan_dma_desc_free_list(struct virt_dma_chan *vc, struct list_head *head) while (!list_empty(head)) { struct virt_dma_desc *vd = list_first_entry(head, struct virt_dma_desc, node); - if (async_tx_test_ack(&vd->tx)) { - list_move_tail(&vd->node, &vc->desc_allocated); - } else { - dev_dbg(vc->chan.device->dev, "txd %p: freeing\n", vd); - list_del(&vd->node); - vc->desc_free(vd); - } + list_del(&vd->node); + dev_dbg(vc->chan.device->dev, "txd %p: freeing\n", vd); + vc->desc_free(vd); } } EXPORT_SYMBOL_GPL(vchan_dma_desc_free_list); @@ -114,7 +108,6 @@ void vchan_init(struct virt_dma_chan *vc, struct dma_device *dmadev) dma_cookie_init(&vc->chan); spin_lock_init(&vc->lock); - INIT_LIST_HEAD(&vc->desc_allocated); INIT_LIST_HEAD(&vc->desc_submitted); INIT_LIST_HEAD(&vc->desc_issued); INIT_LIST_HEAD(&vc->desc_completed); diff --git a/drivers/dma/virt-dma.h b/drivers/dma/virt-dma.h index 189e75dbcb15..181b95267866 100644 --- a/drivers/dma/virt-dma.h +++ b/drivers/dma/virt-dma.h @@ -29,7 +29,6 @@ struct virt_dma_chan { spinlock_t lock; /* protected by vc.lock */ - struct list_head desc_allocated; struct list_head desc_submitted; struct list_head desc_issued; struct list_head desc_completed; @@ -56,16 +55,11 @@ static inline struct dma_async_tx_descriptor *vchan_tx_prep(struct virt_dma_chan struct virt_dma_desc *vd, unsigned long tx_flags) { extern dma_cookie_t vchan_tx_submit(struct dma_async_tx_descriptor *); - unsigned long flags; dma_async_tx_descriptor_init(&vd->tx, &vc->chan); vd->tx.flags = tx_flags; vd->tx.tx_submit = vchan_tx_submit; - spin_lock_irqsave(&vc->lock, flags); - list_add_tail(&vd->node, &vc->desc_allocated); - spin_unlock_irqrestore(&vc->lock, flags); - return &vd->tx; } @@ -128,8 +122,7 @@ static inline struct virt_dma_desc *vchan_next_desc(struct virt_dma_chan *vc) } /** - * vchan_get_all_descriptors - obtain all allocated, submitted and issued - * descriptors + * vchan_get_all_descriptors - obtain all submitted and issued descriptors * vc: virtual channel to get descriptors from * head: list of descriptors found * @@ -141,7 +134,6 @@ static inline struct virt_dma_desc *vchan_next_desc(struct virt_dma_chan *vc) static inline void vchan_get_all_descriptors(struct virt_dma_chan *vc, struct list_head *head) { - list_splice_tail_init(&vc->desc_allocated, head); list_splice_tail_init(&vc->desc_submitted, head); list_splice_tail_init(&vc->desc_issued, head); list_splice_tail_init(&vc->desc_completed, head); @@ -149,14 +141,11 @@ static inline void vchan_get_all_descriptors(struct virt_dma_chan *vc, static inline void vchan_free_chan_resources(struct virt_dma_chan *vc) { - struct virt_dma_desc *vd; unsigned long flags; LIST_HEAD(head); spin_lock_irqsave(&vc->lock, flags); vchan_get_all_descriptors(vc, &head); - list_for_each_entry(vd, &head, node) - async_tx_clear_ack(&vd->tx); spin_unlock_irqrestore(&vc->lock, flags); vchan_dma_desc_free_list(vc, &head); diff --git a/drivers/dma/xgene-dma.c b/drivers/dma/xgene-dma.c index 620fd55ec766..dff22ab01851 100644 --- a/drivers/dma/xgene-dma.c +++ b/drivers/dma/xgene-dma.c @@ -111,6 +111,7 @@ #define XGENE_DMA_MEM_RAM_SHUTDOWN 0xD070 #define XGENE_DMA_BLK_MEM_RDY 0xD074 #define XGENE_DMA_BLK_MEM_RDY_VAL 0xFFFFFFFF +#define XGENE_DMA_RING_CMD_SM_OFFSET 0x8000 /* X-Gene SoC EFUSE csr register and bit defination */ #define XGENE_SOC_JTAG1_SHADOW 0x18 @@ -1887,6 +1888,8 @@ static int xgene_dma_get_resources(struct platform_device *pdev, return -ENOMEM; } + pdma->csr_ring_cmd += XGENE_DMA_RING_CMD_SM_OFFSET; + /* Get efuse csr region */ res = platform_get_resource(pdev, IORESOURCE_MEM, 3); if (!res) { diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c index 080d5cc27055..eebdf2a33bfe 100644 --- a/drivers/extcon/extcon-palmas.c +++ b/drivers/extcon/extcon-palmas.c @@ -200,7 +200,6 @@ static int palmas_usb_probe(struct platform_device *pdev) status = devm_extcon_dev_register(&pdev->dev, palmas_usb->edev); if (status) { dev_err(&pdev->dev, "failed to register extcon device\n"); - kfree(palmas_usb->edev->name); return status; } @@ -214,7 +213,6 @@ static int palmas_usb_probe(struct platform_device *pdev) if (status < 0) { dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", palmas_usb->id_irq, status); - kfree(palmas_usb->edev->name); return status; } } @@ -229,7 +227,6 @@ static int palmas_usb_probe(struct platform_device *pdev) if (status < 0) { dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", palmas_usb->vbus_irq, status); - kfree(palmas_usb->edev->name); return status; } } @@ -239,15 +236,6 @@ static int palmas_usb_probe(struct platform_device *pdev) return 0; } -static int palmas_usb_remove(struct platform_device *pdev) -{ - struct palmas_usb *palmas_usb = platform_get_drvdata(pdev); - - kfree(palmas_usb->edev->name); - - return 0; -} - #ifdef CONFIG_PM_SLEEP static int palmas_usb_suspend(struct device *dev) { @@ -288,7 +276,6 @@ static const struct of_device_id of_palmas_match_tbl[] = { static struct platform_driver palmas_usb_driver = { .probe = palmas_usb_probe, - .remove = palmas_usb_remove, .driver = { .name = "palmas-usb", .of_match_table = of_palmas_match_tbl, diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index 76157ab9faf3..43b57b02d050 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c @@ -124,25 +124,35 @@ static int find_cable_index_by_id(struct extcon_dev *edev, const unsigned int id return -EINVAL; } -static int find_cable_index_by_name(struct extcon_dev *edev, const char *name) +static int find_cable_id_by_name(struct extcon_dev *edev, const char *name) { - unsigned int id = EXTCON_NONE; + unsigned int id = -EINVAL; int i = 0; - if (edev->max_supported == 0) - return -EINVAL; - - /* Find the the number of extcon cable */ + /* Find the id of extcon cable */ while (extcon_name[i]) { if (!strncmp(extcon_name[i], name, CABLE_NAME_MAX)) { id = i; break; } + i++; } - if (id == EXTCON_NONE) + return id; +} + +static int find_cable_index_by_name(struct extcon_dev *edev, const char *name) +{ + unsigned int id; + + if (edev->max_supported == 0) return -EINVAL; + /* Find the the number of extcon cable */ + id = find_cable_id_by_name(edev, name); + if (id < 0) + return id; + return find_cable_index_by_id(edev, id); } @@ -228,9 +238,11 @@ static ssize_t cable_state_show(struct device *dev, struct extcon_cable *cable = container_of(attr, struct extcon_cable, attr_state); + int i = cable->cable_index; + return sprintf(buf, "%d\n", extcon_get_cable_state_(cable->edev, - cable->cable_index)); + cable->edev->supported_cable[i])); } /** @@ -263,20 +275,25 @@ int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state) spin_lock_irqsave(&edev->lock, flags); if (edev->state != ((edev->state & ~mask) | (state & mask))) { + u32 old_state; + if (check_mutually_exclusive(edev, (edev->state & ~mask) | (state & mask))) { spin_unlock_irqrestore(&edev->lock, flags); return -EPERM; } - for (index = 0; index < edev->max_supported; index++) { - if (is_extcon_changed(edev->state, state, index, &attached)) - raw_notifier_call_chain(&edev->nh[index], attached, edev); - } - + old_state = edev->state; edev->state &= ~mask; edev->state |= state & mask; + for (index = 0; index < edev->max_supported; index++) { + if (is_extcon_changed(old_state, edev->state, index, + &attached)) + raw_notifier_call_chain(&edev->nh[index], + attached, edev); + } + /* This could be in interrupt handler */ prop_buf = (char *)get_zeroed_page(GFP_ATOMIC); if (prop_buf) { @@ -361,8 +378,13 @@ EXPORT_SYMBOL_GPL(extcon_get_cable_state_); */ int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name) { - return extcon_get_cable_state_(edev, find_cable_index_by_name - (edev, cable_name)); + unsigned int id; + + id = find_cable_id_by_name(edev, cable_name); + if (id < 0) + return id; + + return extcon_get_cable_state_(edev, id); } EXPORT_SYMBOL_GPL(extcon_get_cable_state); @@ -404,8 +426,13 @@ EXPORT_SYMBOL_GPL(extcon_set_cable_state_); int extcon_set_cable_state(struct extcon_dev *edev, const char *cable_name, bool cable_state) { - return extcon_set_cable_state_(edev, find_cable_index_by_name - (edev, cable_name), cable_state); + unsigned int id; + + id = find_cable_id_by_name(edev, cable_name); + if (id < 0) + return id; + + return extcon_set_cable_state_(edev, id, cable_state); } EXPORT_SYMBOL_GPL(extcon_set_cable_state); diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c index 4fd9961d552e..d42537425438 100644 --- a/drivers/firmware/efi/cper.c +++ b/drivers/firmware/efi/cper.c @@ -305,10 +305,17 @@ const char *cper_mem_err_unpack(struct trace_seq *p, return ret; } -static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem) +static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem, + int len) { struct cper_mem_err_compact cmem; + /* Don't trust UEFI 2.1/2.2 structure with bad validation bits */ + if (len == sizeof(struct cper_sec_mem_err_old) && + (mem->validation_bits & ~(CPER_MEM_VALID_RANK_NUMBER - 1))) { + pr_err(FW_WARN "valid bits set for fields beyond structure\n"); + return; + } if (mem->validation_bits & CPER_MEM_VALID_ERROR_STATUS) printk("%s""error_status: 0x%016llx\n", pfx, mem->error_status); if (mem->validation_bits & CPER_MEM_VALID_PA) @@ -405,8 +412,10 @@ static void cper_estatus_print_section( } else if (!uuid_le_cmp(*sec_type, CPER_SEC_PLATFORM_MEM)) { struct cper_sec_mem_err *mem_err = (void *)(gdata + 1); printk("%s""section_type: memory error\n", newpfx); - if (gdata->error_data_length >= sizeof(*mem_err)) - cper_print_mem(newpfx, mem_err); + if (gdata->error_data_length >= + sizeof(struct cper_sec_mem_err_old)) + cper_print_mem(newpfx, mem_err, + gdata->error_data_length); else goto err_section_too_small; } else if (!uuid_le_cmp(*sec_type, CPER_SEC_PCIE)) { diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 9fa8084a7c8d..d6144e3b97c5 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -58,6 +58,11 @@ bool efi_runtime_disabled(void) static int __init parse_efi_cmdline(char *str) { + if (!str) { + pr_warn("need at least one option\n"); + return -EINVAL; + } + if (parse_option_str(str, "noruntime")) disable_runtime = true; diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c index 7a3cb1fa0a76..4630a8133ea6 100644 --- a/drivers/gpio/gpio-brcmstb.c +++ b/drivers/gpio/gpio-brcmstb.c @@ -87,6 +87,15 @@ static int brcmstb_gpio_remove(struct platform_device *pdev) struct brcmstb_gpio_bank *bank; int ret = 0; + if (!priv) { + dev_err(&pdev->dev, "called %s without drvdata!\n", __func__); + return -EFAULT; + } + + /* + * You can lose return values below, but we report all errors, and it's + * more important to actually perform all of the steps. + */ list_for_each(pos, &priv->bank_list) { bank = list_entry(pos, struct brcmstb_gpio_bank, node); ret = bgpio_remove(&bank->bgc); @@ -143,6 +152,8 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; + platform_set_drvdata(pdev, priv); + INIT_LIST_HEAD(&priv->bank_list); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); reg_base = devm_ioremap_resource(dev, res); @@ -153,7 +164,6 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) priv->reg_base = reg_base; priv->pdev = pdev; - INIT_LIST_HEAD(&priv->bank_list); if (brcmstb_gpio_sanity_check_banks(dev, np, res)) return -EINVAL; @@ -221,8 +231,6 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) dev_info(dev, "Registered %d banks (GPIO(s): %d-%d)\n", priv->num_banks, priv->gpio_base, gpio_base - 1); - platform_set_drvdata(pdev, priv); - return 0; fail: diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index c5e05c82d67c..c246ac3dda7c 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -578,15 +578,13 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) writel_relaxed(~0, &g->clr_falling); writel_relaxed(~0, &g->clr_rising); - /* set up all irqs in this bank */ - irq_set_chained_handler(bank_irq, gpio_irq_handler); - /* * Each chip handles 32 gpios, and each irq bank consists of 16 * gpio irqs. Pass the irq bank's corresponding controller to * the chained irq handler. */ - irq_set_handler_data(bank_irq, &chips[gpio / 32]); + irq_set_chained_handler_and_data(bank_irq, gpio_irq_handler, + &chips[gpio / 32]); binten |= BIT(bank); } diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c index aed4ca9338bc..7d3c90e9da71 100644 --- a/drivers/gpio/gpio-max732x.c +++ b/drivers/gpio/gpio-max732x.c @@ -603,6 +603,7 @@ static int max732x_setup_gpio(struct max732x_chip *chip, gc->base = gpio_start; gc->ngpio = port; gc->label = chip->client->name; + gc->dev = &chip->client->dev; gc->owner = THIS_MODULE; return port; diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index b0c57d505be7..61a731ff9a07 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -500,8 +500,10 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type) spin_lock_irqsave(&bank->lock, flags); retval = omap_set_gpio_triggering(bank, offset, type); - if (retval) + if (retval) { + spin_unlock_irqrestore(&bank->lock, flags); goto error; + } omap_gpio_init_irq(bank, offset); if (!omap_gpio_is_input(bank, offset)) { spin_unlock_irqrestore(&bank->lock, flags); @@ -1185,6 +1187,7 @@ static int omap_gpio_probe(struct platform_device *pdev) bank->irq = res->start; bank->dev = dev; bank->chip.dev = dev; + bank->chip.owner = THIS_MODULE; bank->dbck_flag = pdata->dbck_flag; bank->stride = pdata->bank_stride; bank->width = pdata->bank_width; diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index d233eb3b8132..50caeb1ee350 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -570,6 +570,10 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, "could not connect irqchip to gpiochip\n"); return ret; } + + gpiochip_set_chained_irqchip(&chip->gpio_chip, + &pca953x_irq_chip, + client->irq, NULL); } return 0; diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index 77fe5d3cb105..d5284dfe01fe 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -220,9 +220,9 @@ static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc) if (!chip->gpio_width[1]) return; - xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET + XGPIO_TRI_OFFSET, + xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET + XGPIO_CHANNEL_OFFSET, chip->gpio_state[1]); - xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET + XGPIO_TRI_OFFSET, + xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET + XGPIO_CHANNEL_OFFSET, chip->gpio_dir[1]); } diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 2e87c4b8da26..a78882389836 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -757,6 +757,7 @@ static int zynq_gpio_remove(struct platform_device *pdev) gpiochip_remove(&gpio->chip); clk_disable_unprepare(gpio->clk); device_set_wakeup_capable(&pdev->dev, 0); + pm_runtime_disable(&pdev->dev); return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 01657830b470..f7b49d5ce4b8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1130,6 +1130,9 @@ struct amdgpu_gfx { uint32_t me_feature_version; uint32_t ce_feature_version; uint32_t pfp_feature_version; + uint32_t rlc_feature_version; + uint32_t mec_feature_version; + uint32_t mec2_feature_version; struct amdgpu_ring gfx_ring[AMDGPU_MAX_GFX_RINGS]; unsigned num_gfx_rings; struct amdgpu_ring compute_ring[AMDGPU_MAX_COMPUTE_RINGS]; @@ -1614,6 +1617,9 @@ struct amdgpu_uvd { #define AMDGPU_MAX_VCE_HANDLES 16 #define AMDGPU_VCE_FIRMWARE_OFFSET 256 +#define AMDGPU_VCE_HARVEST_VCE0 (1 << 0) +#define AMDGPU_VCE_HARVEST_VCE1 (1 << 1) + struct amdgpu_vce { struct amdgpu_bo *vcpu_bo; uint64_t gpu_addr; @@ -1626,6 +1632,7 @@ struct amdgpu_vce { const struct firmware *fw; /* VCE firmware */ struct amdgpu_ring ring[AMDGPU_MAX_VCE_RINGS]; struct amdgpu_irq_src irq; + unsigned harvest_config; }; /* @@ -1635,6 +1642,7 @@ struct amdgpu_sdma { /* SDMA firmware */ const struct firmware *fw; uint32_t fw_version; + uint32_t feature_version; struct amdgpu_ring ring; }; @@ -1862,6 +1870,12 @@ typedef void (*amdgpu_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t); typedef uint32_t (*amdgpu_block_rreg_t)(struct amdgpu_device*, uint32_t, uint32_t); typedef void (*amdgpu_block_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t, uint32_t); +struct amdgpu_ip_block_status { + bool valid; + bool sw; + bool hw; +}; + struct amdgpu_device { struct device *dev; struct drm_device *ddev; @@ -2004,7 +2018,7 @@ struct amdgpu_device { const struct amdgpu_ip_block_version *ip_blocks; int num_ip_blocks; - bool *ip_block_enabled; + struct amdgpu_ip_block_status *ip_block_status; struct mutex mn_lock; DECLARE_HASHTABLE(mn_hash, 7); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index d63135bf29c0..1f040d85ac47 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -669,6 +669,7 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev, static int amdgpu_cs_dependencies(struct amdgpu_device *adev, struct amdgpu_cs_parser *p) { + struct amdgpu_fpriv *fpriv = p->filp->driver_priv; struct amdgpu_ib *ib; int i, j, r; @@ -694,6 +695,7 @@ static int amdgpu_cs_dependencies(struct amdgpu_device *adev, for (j = 0; j < num_deps; ++j) { struct amdgpu_fence *fence; struct amdgpu_ring *ring; + struct amdgpu_ctx *ctx; r = amdgpu_cs_get_ring(adev, deps[j].ip_type, deps[j].ip_instance, @@ -701,14 +703,21 @@ static int amdgpu_cs_dependencies(struct amdgpu_device *adev, if (r) return r; + ctx = amdgpu_ctx_get(fpriv, deps[j].ctx_id); + if (ctx == NULL) + return -EINVAL; + r = amdgpu_fence_recreate(ring, p->filp, deps[j].handle, &fence); - if (r) + if (r) { + amdgpu_ctx_put(ctx); return r; + } amdgpu_sync_fence(&ib->sync, fence); amdgpu_fence_unref(&fence); + amdgpu_ctx_put(ctx); } } @@ -808,12 +817,16 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data, r = amdgpu_cs_get_ring(adev, wait->in.ip_type, wait->in.ip_instance, wait->in.ring, &ring); - if (r) + if (r) { + amdgpu_ctx_put(ctx); return r; + } r = amdgpu_fence_recreate(ring, filp, wait->in.handle, &fence); - if (r) + if (r) { + amdgpu_ctx_put(ctx); return r; + } r = fence_wait_timeout(&fence->base, true, timeout); amdgpu_fence_unref(&fence); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index ba46be361c9b..99f158e1baff 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1191,8 +1191,9 @@ static int amdgpu_early_init(struct amdgpu_device *adev) return -EINVAL; } - adev->ip_block_enabled = kcalloc(adev->num_ip_blocks, sizeof(bool), GFP_KERNEL); - if (adev->ip_block_enabled == NULL) + adev->ip_block_status = kcalloc(adev->num_ip_blocks, + sizeof(struct amdgpu_ip_block_status), GFP_KERNEL); + if (adev->ip_block_status == NULL) return -ENOMEM; if (adev->ip_blocks == NULL) { @@ -1203,14 +1204,19 @@ static int amdgpu_early_init(struct amdgpu_device *adev) for (i = 0; i < adev->num_ip_blocks; i++) { if ((amdgpu_ip_block_mask & (1 << i)) == 0) { DRM_ERROR("disabled ip block: %d\n", i); - adev->ip_block_enabled[i] = false; + adev->ip_block_status[i].valid = false; } else { if (adev->ip_blocks[i].funcs->early_init) { r = adev->ip_blocks[i].funcs->early_init((void *)adev); - if (r) + if (r == -ENOENT) + adev->ip_block_status[i].valid = false; + else if (r) return r; + else + adev->ip_block_status[i].valid = true; + } else { + adev->ip_block_status[i].valid = true; } - adev->ip_block_enabled[i] = true; } } @@ -1222,11 +1228,12 @@ static int amdgpu_init(struct amdgpu_device *adev) int i, r; for (i = 0; i < adev->num_ip_blocks; i++) { - if (!adev->ip_block_enabled[i]) + if (!adev->ip_block_status[i].valid) continue; r = adev->ip_blocks[i].funcs->sw_init((void *)adev); if (r) return r; + adev->ip_block_status[i].sw = true; /* need to do gmc hw init early so we can allocate gpu mem */ if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) { r = amdgpu_vram_scratch_init(adev); @@ -1238,11 +1245,12 @@ static int amdgpu_init(struct amdgpu_device *adev) r = amdgpu_wb_init(adev); if (r) return r; + adev->ip_block_status[i].hw = true; } } for (i = 0; i < adev->num_ip_blocks; i++) { - if (!adev->ip_block_enabled[i]) + if (!adev->ip_block_status[i].sw) continue; /* gmc hw init is done early */ if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) @@ -1250,6 +1258,7 @@ static int amdgpu_init(struct amdgpu_device *adev) r = adev->ip_blocks[i].funcs->hw_init((void *)adev); if (r) return r; + adev->ip_block_status[i].hw = true; } return 0; @@ -1260,7 +1269,7 @@ static int amdgpu_late_init(struct amdgpu_device *adev) int i = 0, r; for (i = 0; i < adev->num_ip_blocks; i++) { - if (!adev->ip_block_enabled[i]) + if (!adev->ip_block_status[i].valid) continue; /* enable clockgating to save power */ r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, @@ -1282,7 +1291,7 @@ static int amdgpu_fini(struct amdgpu_device *adev) int i, r; for (i = adev->num_ip_blocks - 1; i >= 0; i--) { - if (!adev->ip_block_enabled[i]) + if (!adev->ip_block_status[i].hw) continue; if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) { amdgpu_wb_fini(adev); @@ -1295,14 +1304,16 @@ static int amdgpu_fini(struct amdgpu_device *adev) return r; r = adev->ip_blocks[i].funcs->hw_fini((void *)adev); /* XXX handle errors */ + adev->ip_block_status[i].hw = false; } for (i = adev->num_ip_blocks - 1; i >= 0; i--) { - if (!adev->ip_block_enabled[i]) + if (!adev->ip_block_status[i].sw) continue; r = adev->ip_blocks[i].funcs->sw_fini((void *)adev); /* XXX handle errors */ - adev->ip_block_enabled[i] = false; + adev->ip_block_status[i].sw = false; + adev->ip_block_status[i].valid = false; } return 0; @@ -1313,7 +1324,7 @@ static int amdgpu_suspend(struct amdgpu_device *adev) int i, r; for (i = adev->num_ip_blocks - 1; i >= 0; i--) { - if (!adev->ip_block_enabled[i]) + if (!adev->ip_block_status[i].valid) continue; /* ungate blocks so that suspend can properly shut them down */ r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, @@ -1331,7 +1342,7 @@ static int amdgpu_resume(struct amdgpu_device *adev) int i, r; for (i = 0; i < adev->num_ip_blocks; i++) { - if (!adev->ip_block_enabled[i]) + if (!adev->ip_block_status[i].valid) continue; r = adev->ip_blocks[i].funcs->resume(adev); if (r) @@ -1577,8 +1588,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev) amdgpu_fence_driver_fini(adev); amdgpu_fbdev_fini(adev); r = amdgpu_fini(adev); - kfree(adev->ip_block_enabled); - adev->ip_block_enabled = NULL; + kfree(adev->ip_block_status); + adev->ip_block_status = NULL; adev->accel_working = false; /* free i2c buses */ amdgpu_i2c_fini(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 975edb1000a2..4afc507820c0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -352,7 +352,7 @@ unsigned long amdgpu_gem_timeout(uint64_t timeout_ns) if (((int64_t)timeout_ns) < 0) return MAX_SCHEDULE_TIMEOUT; - timeout = ktime_sub_ns(ktime_get(), timeout_ns); + timeout = ktime_sub(ns_to_ktime(timeout_ns), ktime_get()); if (ktime_to_ns(timeout) < 0) return 0; @@ -449,7 +449,7 @@ out: * vital here, so they are not reported back to userspace. */ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, - struct amdgpu_bo_va *bo_va) + struct amdgpu_bo_va *bo_va, uint32_t operation) { struct ttm_validate_buffer tv, *entry; struct amdgpu_bo_list_entry *vm_bos; @@ -485,7 +485,9 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, if (r) goto error_unlock; - r = amdgpu_vm_bo_update(adev, bo_va, &bo_va->bo->tbo.mem); + + if (operation == AMDGPU_VA_OP_MAP) + r = amdgpu_vm_bo_update(adev, bo_va, &bo_va->bo->tbo.mem); error_unlock: mutex_unlock(&bo_va->vm->mutex); @@ -580,7 +582,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, } if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE)) - amdgpu_gem_va_update_vm(adev, bo_va); + amdgpu_gem_va_update_vm(adev, bo_va, args->operation); drm_gem_object_unreference_unlocked(gobj); return r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index 52dff75aac6f..bc0fac618a3f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -180,16 +180,16 @@ int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs, if (vm) { /* do context switch */ amdgpu_vm_flush(ring, vm, ib->sync.last_vm_update); - } - if (vm && ring->funcs->emit_gds_switch) - amdgpu_ring_emit_gds_switch(ring, ib->vm->ids[ring->idx].id, - ib->gds_base, ib->gds_size, - ib->gws_base, ib->gws_size, - ib->oa_base, ib->oa_size); + if (ring->funcs->emit_gds_switch) + amdgpu_ring_emit_gds_switch(ring, ib->vm->ids[ring->idx].id, + ib->gds_base, ib->gds_size, + ib->gws_base, ib->gws_size, + ib->oa_base, ib->oa_size); - if (ring->funcs->emit_hdp_flush) - amdgpu_ring_emit_hdp_flush(ring); + if (ring->funcs->emit_hdp_flush) + amdgpu_ring_emit_hdp_flush(ring); + } old_ctx = ring->current_ctx; for (i = 0; i < num_ibs; ++i) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 5533434c7a8f..3bfe67de8349 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -235,7 +235,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file for (i = 0; i < adev->num_ip_blocks; i++) { if (adev->ip_blocks[i].type == type && - adev->ip_block_enabled[i]) { + adev->ip_block_status[i].valid) { ip.hw_ip_version_major = adev->ip_blocks[i].major; ip.hw_ip_version_minor = adev->ip_blocks[i].minor; ip.capabilities_flags = 0; @@ -274,7 +274,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file for (i = 0; i < adev->num_ip_blocks; i++) if (adev->ip_blocks[i].type == type && - adev->ip_block_enabled[i] && + adev->ip_block_status[i].valid && count < AMDGPU_HW_IP_INSTANCE_MAX_COUNT) count++; @@ -317,16 +317,17 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file break; case AMDGPU_INFO_FW_GFX_RLC: fw_info.ver = adev->gfx.rlc_fw_version; - fw_info.feature = 0; + fw_info.feature = adev->gfx.rlc_feature_version; break; case AMDGPU_INFO_FW_GFX_MEC: - if (info->query_fw.index == 0) + if (info->query_fw.index == 0) { fw_info.ver = adev->gfx.mec_fw_version; - else if (info->query_fw.index == 1) + fw_info.feature = adev->gfx.mec_feature_version; + } else if (info->query_fw.index == 1) { fw_info.ver = adev->gfx.mec2_fw_version; - else + fw_info.feature = adev->gfx.mec2_feature_version; + } else return -EINVAL; - fw_info.feature = 0; break; case AMDGPU_INFO_FW_SMC: fw_info.ver = adev->pm.fw_version; @@ -336,7 +337,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file if (info->query_fw.index >= 2) return -EINVAL; fw_info.ver = adev->sdma[info->query_fw.index].fw_version; - fw_info.feature = 0; + fw_info.feature = adev->sdma[info->query_fw.index].feature_version; break; default: return -EINVAL; @@ -416,7 +417,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file return n ? -EFAULT : 0; } case AMDGPU_INFO_DEV_INFO: { - struct drm_amdgpu_info_device dev_info; + struct drm_amdgpu_info_device dev_info = {}; struct amdgpu_cu_info cu_info; dev_info.device_id = dev->pdev->device; @@ -459,6 +460,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file memcpy(&dev_info.cu_bitmap[0], &cu_info.bitmap[0], sizeof(cu_info.bitmap)); dev_info.vram_type = adev->mc.vram_type; dev_info.vram_bit_width = adev->mc.vram_width; + dev_info.vce_harvest_config = adev->vce.harvest_config; return copy_to_user(out, &dev_info, min((size_t)size, sizeof(dev_info))) ? -EFAULT : 0; diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c index ab83cc1ca4cc..15df46c93f0a 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c @@ -500,6 +500,7 @@ static int cik_sdma_load_microcode(struct amdgpu_device *adev) amdgpu_ucode_print_sdma_hdr(&hdr->header); fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4; adev->sdma[i].fw_version = le32_to_cpu(hdr->header.ucode_version); + adev->sdma[i].feature_version = le32_to_cpu(hdr->ucode_feature_version); fw_data = (const __le32 *) (adev->sdma[i].fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); WREG32(mmSDMA0_UCODE_ADDR + sdma_offsets[i], 0); diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c index f75a31df30bd..ace870afc7d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c @@ -494,29 +494,67 @@ static void cz_dpm_fini(struct amdgpu_device *adev) amdgpu_free_extended_power_table(adev); } +#define ixSMUSVI_NB_CURRENTVID 0xD8230044 +#define CURRENT_NB_VID_MASK 0xff000000 +#define CURRENT_NB_VID__SHIFT 24 +#define ixSMUSVI_GFX_CURRENTVID 0xD8230048 +#define CURRENT_GFX_VID_MASK 0xff000000 +#define CURRENT_GFX_VID__SHIFT 24 + static void cz_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev, struct seq_file *m) { + struct cz_power_info *pi = cz_get_pi(adev); struct amdgpu_clock_voltage_dependency_table *table = &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; - u32 current_index = - (RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX) & - TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX_MASK) >> - TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX__SHIFT; - u32 sclk, tmp; - u16 vddc; - - if (current_index >= NUM_SCLK_LEVELS) { - seq_printf(m, "invalid dpm profile %d\n", current_index); + struct amdgpu_uvd_clock_voltage_dependency_table *uvd_table = + &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table; + struct amdgpu_vce_clock_voltage_dependency_table *vce_table = + &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; + u32 sclk_index = REG_GET_FIELD(RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX), + TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX); + u32 uvd_index = REG_GET_FIELD(RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX_2), + TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_UVD_INDEX); + u32 vce_index = REG_GET_FIELD(RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX_2), + TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_VCE_INDEX); + u32 sclk, vclk, dclk, ecclk, tmp; + u16 vddnb, vddgfx; + + if (sclk_index >= NUM_SCLK_LEVELS) { + seq_printf(m, "invalid sclk dpm profile %d\n", sclk_index); } else { - sclk = table->entries[current_index].clk; - tmp = (RREG32_SMC(ixSMU_VOLTAGE_STATUS) & - SMU_VOLTAGE_STATUS__SMU_VOLTAGE_CURRENT_LEVEL_MASK) >> - SMU_VOLTAGE_STATUS__SMU_VOLTAGE_CURRENT_LEVEL__SHIFT; - vddc = cz_convert_8bit_index_to_voltage(adev, (u16)tmp); - seq_printf(m, "power level %d sclk: %u vddc: %u\n", - current_index, sclk, vddc); + sclk = table->entries[sclk_index].clk; + seq_printf(m, "%u sclk: %u\n", sclk_index, sclk); + } + + tmp = (RREG32_SMC(ixSMUSVI_NB_CURRENTVID) & + CURRENT_NB_VID_MASK) >> CURRENT_NB_VID__SHIFT; + vddnb = cz_convert_8bit_index_to_voltage(adev, (u16)tmp); + tmp = (RREG32_SMC(ixSMUSVI_GFX_CURRENTVID) & + CURRENT_GFX_VID_MASK) >> CURRENT_GFX_VID__SHIFT; + vddgfx = cz_convert_8bit_index_to_voltage(adev, (u16)tmp); + seq_printf(m, "vddnb: %u vddgfx: %u\n", vddnb, vddgfx); + + seq_printf(m, "uvd %sabled\n", pi->uvd_power_gated ? "dis" : "en"); + if (!pi->uvd_power_gated) { + if (uvd_index >= CZ_MAX_HARDWARE_POWERLEVELS) { + seq_printf(m, "invalid uvd dpm level %d\n", uvd_index); + } else { + vclk = uvd_table->entries[uvd_index].vclk; + dclk = uvd_table->entries[uvd_index].dclk; + seq_printf(m, "%u uvd vclk: %u dclk: %u\n", uvd_index, vclk, dclk); + } + } + + seq_printf(m, "vce %sabled\n", pi->vce_power_gated ? "dis" : "en"); + if (!pi->vce_power_gated) { + if (vce_index >= CZ_MAX_HARDWARE_POWERLEVELS) { + seq_printf(m, "invalid vce dpm level %d\n", vce_index); + } else { + ecclk = vce_table->entries[vce_index].ecclk; + seq_printf(m, "%u vce ecclk: %u\n", vce_index, ecclk); + } } } @@ -1679,25 +1717,31 @@ static int cz_dpm_unforce_dpm_levels(struct amdgpu_device *adev) if (ret) return ret; - DRM_INFO("DPM unforce state min=%d, max=%d.\n", - pi->sclk_dpm.soft_min_clk, - pi->sclk_dpm.soft_max_clk); + DRM_DEBUG("DPM unforce state min=%d, max=%d.\n", + pi->sclk_dpm.soft_min_clk, + pi->sclk_dpm.soft_max_clk); return 0; } static int cz_dpm_force_dpm_level(struct amdgpu_device *adev, - enum amdgpu_dpm_forced_level level) + enum amdgpu_dpm_forced_level level) { int ret = 0; switch (level) { case AMDGPU_DPM_FORCED_LEVEL_HIGH: + ret = cz_dpm_unforce_dpm_levels(adev); + if (ret) + return ret; ret = cz_dpm_force_highest(adev); if (ret) return ret; break; case AMDGPU_DPM_FORCED_LEVEL_LOW: + ret = cz_dpm_unforce_dpm_levels(adev); + if (ret) + return ret; ret = cz_dpm_force_lowest(adev); if (ret) return ret; @@ -1711,6 +1755,8 @@ static int cz_dpm_force_dpm_level(struct amdgpu_device *adev, break; } + adev->pm.dpm.forced_level = level; + return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 5cde635978f9..e70a26f587a0 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -2632,6 +2632,7 @@ static void dce_v10_0_crtc_dpms(struct drm_crtc *crtc, int mode) struct drm_device *dev = crtc->dev; struct amdgpu_device *adev = dev->dev_private; struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + unsigned type; switch (mode) { case DRM_MODE_DPMS_ON: @@ -2640,6 +2641,9 @@ static void dce_v10_0_crtc_dpms(struct drm_crtc *crtc, int mode) dce_v10_0_vga_enable(crtc, true); amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE); dce_v10_0_vga_enable(crtc, false); + /* Make sure VBLANK interrupt is still enabled */ + type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id); + amdgpu_irq_update(adev, &adev->crtc_irq, type); drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id); dce_v10_0_crtc_load_lut(crtc); break; @@ -3403,19 +3407,25 @@ static int dce_v10_0_crtc_irq(struct amdgpu_device *adev, switch (entry->src_data) { case 0: /* vblank */ - if (disp_int & interrupt_status_offsets[crtc].vblank) { + if (disp_int & interrupt_status_offsets[crtc].vblank) dce_v10_0_crtc_vblank_int_ack(adev, crtc); - if (amdgpu_irq_enabled(adev, source, irq_type)) { - drm_handle_vblank(adev->ddev, crtc); - } - DRM_DEBUG("IH: D%d vblank\n", crtc + 1); + else + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (amdgpu_irq_enabled(adev, source, irq_type)) { + drm_handle_vblank(adev->ddev, crtc); } + DRM_DEBUG("IH: D%d vblank\n", crtc + 1); + break; case 1: /* vline */ - if (disp_int & interrupt_status_offsets[crtc].vline) { + if (disp_int & interrupt_status_offsets[crtc].vline) dce_v10_0_crtc_vline_int_ack(adev, crtc); - DRM_DEBUG("IH: D%d vline\n", crtc + 1); - } + else + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + DRM_DEBUG("IH: D%d vline\n", crtc + 1); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 95efd98b202d..dcb402ee048a 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -2631,6 +2631,7 @@ static void dce_v11_0_crtc_dpms(struct drm_crtc *crtc, int mode) struct drm_device *dev = crtc->dev; struct amdgpu_device *adev = dev->dev_private; struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + unsigned type; switch (mode) { case DRM_MODE_DPMS_ON: @@ -2639,6 +2640,9 @@ static void dce_v11_0_crtc_dpms(struct drm_crtc *crtc, int mode) dce_v11_0_vga_enable(crtc, true); amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE); dce_v11_0_vga_enable(crtc, false); + /* Make sure VBLANK interrupt is still enabled */ + type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id); + amdgpu_irq_update(adev, &adev->crtc_irq, type); drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id); dce_v11_0_crtc_load_lut(crtc); break; @@ -3402,19 +3406,25 @@ static int dce_v11_0_crtc_irq(struct amdgpu_device *adev, switch (entry->src_data) { case 0: /* vblank */ - if (disp_int & interrupt_status_offsets[crtc].vblank) { + if (disp_int & interrupt_status_offsets[crtc].vblank) dce_v11_0_crtc_vblank_int_ack(adev, crtc); - if (amdgpu_irq_enabled(adev, source, irq_type)) { - drm_handle_vblank(adev->ddev, crtc); - } - DRM_DEBUG("IH: D%d vblank\n", crtc + 1); + else + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (amdgpu_irq_enabled(adev, source, irq_type)) { + drm_handle_vblank(adev->ddev, crtc); } + DRM_DEBUG("IH: D%d vblank\n", crtc + 1); + break; case 1: /* vline */ - if (disp_int & interrupt_status_offsets[crtc].vline) { + if (disp_int & interrupt_status_offsets[crtc].vline) dce_v11_0_crtc_vline_int_ack(adev, crtc); - DRM_DEBUG("IH: D%d vline\n", crtc + 1); - } + else + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + DRM_DEBUG("IH: D%d vline\n", crtc + 1); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index aaca8d663f2c..cc050a329c49 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -2566,6 +2566,7 @@ static void dce_v8_0_crtc_dpms(struct drm_crtc *crtc, int mode) struct drm_device *dev = crtc->dev; struct amdgpu_device *adev = dev->dev_private; struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + unsigned type; switch (mode) { case DRM_MODE_DPMS_ON: @@ -2574,6 +2575,9 @@ static void dce_v8_0_crtc_dpms(struct drm_crtc *crtc, int mode) dce_v8_0_vga_enable(crtc, true); amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE); dce_v8_0_vga_enable(crtc, false); + /* Make sure VBLANK interrupt is still enabled */ + type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id); + amdgpu_irq_update(adev, &adev->crtc_irq, type); drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id); dce_v8_0_crtc_load_lut(crtc); break; @@ -3237,19 +3241,25 @@ static int dce_v8_0_crtc_irq(struct amdgpu_device *adev, switch (entry->src_data) { case 0: /* vblank */ - if (disp_int & interrupt_status_offsets[crtc].vblank) { + if (disp_int & interrupt_status_offsets[crtc].vblank) WREG32(mmLB_VBLANK_STATUS + crtc_offsets[crtc], LB_VBLANK_STATUS__VBLANK_ACK_MASK); - if (amdgpu_irq_enabled(adev, source, irq_type)) { - drm_handle_vblank(adev->ddev, crtc); - } - DRM_DEBUG("IH: D%d vblank\n", crtc + 1); + else + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (amdgpu_irq_enabled(adev, source, irq_type)) { + drm_handle_vblank(adev->ddev, crtc); } + DRM_DEBUG("IH: D%d vblank\n", crtc + 1); + break; case 1: /* vline */ - if (disp_int & interrupt_status_offsets[crtc].vline) { + if (disp_int & interrupt_status_offsets[crtc].vline) WREG32(mmLB_VLINE_STATUS + crtc_offsets[crtc], LB_VLINE_STATUS__VLINE_ACK_MASK); - DRM_DEBUG("IH: D%d vline\n", crtc + 1); - } + else + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + DRM_DEBUG("IH: D%d vline\n", crtc + 1); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index 2c188fb9fd22..0d8bf2cb1956 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -2561,7 +2561,7 @@ static bool gfx_v7_0_ring_emit_semaphore(struct amdgpu_ring *ring, * sheduling on the ring. This function schedules the IB * on the gfx ring for execution by the GPU. */ -static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring, +static void gfx_v7_0_ring_emit_ib_gfx(struct amdgpu_ring *ring, struct amdgpu_ib *ib) { bool need_ctx_switch = ring->current_ctx != ib->ctx; @@ -2569,15 +2569,10 @@ static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring, u32 next_rptr = ring->wptr + 5; /* drop the CE preamble IB for the same context */ - if ((ring->type == AMDGPU_RING_TYPE_GFX) && - (ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && - !need_ctx_switch) + if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && !need_ctx_switch) return; - if (ring->type == AMDGPU_RING_TYPE_COMPUTE) - control |= INDIRECT_BUFFER_VALID; - - if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) + if (need_ctx_switch) next_rptr += 2; next_rptr += 4; @@ -2588,7 +2583,7 @@ static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring, amdgpu_ring_write(ring, next_rptr); /* insert SWITCH_BUFFER packet before first IB in the ring frame */ - if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) { + if (need_ctx_switch) { amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); amdgpu_ring_write(ring, 0); } @@ -2611,6 +2606,35 @@ static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring, amdgpu_ring_write(ring, control); } +static void gfx_v7_0_ring_emit_ib_compute(struct amdgpu_ring *ring, + struct amdgpu_ib *ib) +{ + u32 header, control = 0; + u32 next_rptr = ring->wptr + 5; + + control |= INDIRECT_BUFFER_VALID; + next_rptr += 4; + amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); + amdgpu_ring_write(ring, WRITE_DATA_DST_SEL(5) | WR_CONFIRM); + amdgpu_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); + amdgpu_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xffffffff); + amdgpu_ring_write(ring, next_rptr); + + header = PACKET3(PACKET3_INDIRECT_BUFFER, 2); + + control |= ib->length_dw | + (ib->vm ? (ib->vm->ids[ring->idx].id << 24) : 0); + + amdgpu_ring_write(ring, header); + amdgpu_ring_write(ring, +#ifdef __BIG_ENDIAN + (2 << 0) | +#endif + (ib->gpu_addr & 0xFFFFFFFC)); + amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFFFF); + amdgpu_ring_write(ring, control); +} + /** * gfx_v7_0_ring_test_ib - basic ring IB test * @@ -3056,6 +3080,8 @@ static int gfx_v7_0_cp_compute_load_microcode(struct amdgpu_device *adev) mec_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data; amdgpu_ucode_print_gfx_hdr(&mec_hdr->header); adev->gfx.mec_fw_version = le32_to_cpu(mec_hdr->header.ucode_version); + adev->gfx.mec_feature_version = le32_to_cpu( + mec_hdr->ucode_feature_version); gfx_v7_0_cp_compute_enable(adev, false); @@ -3078,6 +3104,8 @@ static int gfx_v7_0_cp_compute_load_microcode(struct amdgpu_device *adev) mec2_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec2_fw->data; amdgpu_ucode_print_gfx_hdr(&mec2_hdr->header); adev->gfx.mec2_fw_version = le32_to_cpu(mec2_hdr->header.ucode_version); + adev->gfx.mec2_feature_version = le32_to_cpu( + mec2_hdr->ucode_feature_version); /* MEC2 */ fw_data = (const __le32 *) @@ -4042,6 +4070,8 @@ static int gfx_v7_0_rlc_resume(struct amdgpu_device *adev) hdr = (const struct rlc_firmware_header_v1_0 *)adev->gfx.rlc_fw->data; amdgpu_ucode_print_rlc_hdr(&hdr->header); adev->gfx.rlc_fw_version = le32_to_cpu(hdr->header.ucode_version); + adev->gfx.rlc_feature_version = le32_to_cpu( + hdr->ucode_feature_version); gfx_v7_0_rlc_stop(adev); @@ -5098,7 +5128,7 @@ static void gfx_v7_0_print_status(void *handle) dev_info(adev->dev, " CP_HPD_EOP_CONTROL=0x%08X\n", RREG32(mmCP_HPD_EOP_CONTROL)); - for (queue = 0; queue < 8; i++) { + for (queue = 0; queue < 8; queue++) { cik_srbm_select(adev, me, pipe, queue, 0); dev_info(adev->dev, " queue: %d\n", queue); dev_info(adev->dev, " CP_PQ_WPTR_POLL_CNTL=0x%08X\n", @@ -5555,7 +5585,7 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = { .get_wptr = gfx_v7_0_ring_get_wptr_gfx, .set_wptr = gfx_v7_0_ring_set_wptr_gfx, .parse_cs = NULL, - .emit_ib = gfx_v7_0_ring_emit_ib, + .emit_ib = gfx_v7_0_ring_emit_ib_gfx, .emit_fence = gfx_v7_0_ring_emit_fence_gfx, .emit_semaphore = gfx_v7_0_ring_emit_semaphore, .emit_vm_flush = gfx_v7_0_ring_emit_vm_flush, @@ -5571,7 +5601,7 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = { .get_wptr = gfx_v7_0_ring_get_wptr_compute, .set_wptr = gfx_v7_0_ring_set_wptr_compute, .parse_cs = NULL, - .emit_ib = gfx_v7_0_ring_emit_ib, + .emit_ib = gfx_v7_0_ring_emit_ib_compute, .emit_fence = gfx_v7_0_ring_emit_fence_compute, .emit_semaphore = gfx_v7_0_ring_emit_semaphore, .emit_vm_flush = gfx_v7_0_ring_emit_vm_flush, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 7b683fb2173c..f5a42ab1f65c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -587,6 +587,7 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev) int err; struct amdgpu_firmware_info *info = NULL; const struct common_firmware_header *header = NULL; + const struct gfx_firmware_header_v1_0 *cp_hdr; DRM_DEBUG("\n"); @@ -611,6 +612,9 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev) err = amdgpu_ucode_validate(adev->gfx.pfp_fw); if (err) goto out; + cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.pfp_fw->data; + adev->gfx.pfp_fw_version = le32_to_cpu(cp_hdr->header.ucode_version); + adev->gfx.pfp_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version); snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", chip_name); err = request_firmware(&adev->gfx.me_fw, fw_name, adev->dev); @@ -619,6 +623,9 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev) err = amdgpu_ucode_validate(adev->gfx.me_fw); if (err) goto out; + cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.me_fw->data; + adev->gfx.me_fw_version = le32_to_cpu(cp_hdr->header.ucode_version); + adev->gfx.me_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version); snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name); err = request_firmware(&adev->gfx.ce_fw, fw_name, adev->dev); @@ -627,12 +634,18 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev) err = amdgpu_ucode_validate(adev->gfx.ce_fw); if (err) goto out; + cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.ce_fw->data; + adev->gfx.ce_fw_version = le32_to_cpu(cp_hdr->header.ucode_version); + adev->gfx.ce_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version); snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name); err = request_firmware(&adev->gfx.rlc_fw, fw_name, adev->dev); if (err) goto out; err = amdgpu_ucode_validate(adev->gfx.rlc_fw); + cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.rlc_fw->data; + adev->gfx.rlc_fw_version = le32_to_cpu(cp_hdr->header.ucode_version); + adev->gfx.rlc_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version); snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", chip_name); err = request_firmware(&adev->gfx.mec_fw, fw_name, adev->dev); @@ -641,6 +654,9 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev) err = amdgpu_ucode_validate(adev->gfx.mec_fw); if (err) goto out; + cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data; + adev->gfx.mec_fw_version = le32_to_cpu(cp_hdr->header.ucode_version); + adev->gfx.mec_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version); snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name); err = request_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev); @@ -648,6 +664,12 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev) err = amdgpu_ucode_validate(adev->gfx.mec2_fw); if (err) goto out; + cp_hdr = (const struct gfx_firmware_header_v1_0 *) + adev->gfx.mec2_fw->data; + adev->gfx.mec2_fw_version = le32_to_cpu( + cp_hdr->header.ucode_version); + adev->gfx.mec2_feature_version = le32_to_cpu( + cp_hdr->ucode_feature_version); } else { err = 0; adev->gfx.mec2_fw = NULL; @@ -1813,10 +1835,7 @@ static u32 gfx_v8_0_get_rb_disabled(struct amdgpu_device *adev, u32 data, mask; data = RREG32(mmCC_RB_BACKEND_DISABLE); - if (data & 1) - data &= CC_RB_BACKEND_DISABLE__BACKEND_DISABLE_MASK; - else - data = 0; + data &= CC_RB_BACKEND_DISABLE__BACKEND_DISABLE_MASK; data |= RREG32(mmGC_USER_RB_BACKEND_DISABLE); @@ -1986,6 +2005,7 @@ static void gfx_v8_0_gpu_init(struct amdgpu_device *adev) adev->gfx.config.max_shader_engines = 1; adev->gfx.config.max_tile_pipes = 2; adev->gfx.config.max_sh_per_se = 1; + adev->gfx.config.max_backends_per_se = 2; switch (adev->pdev->revision) { case 0xc4: @@ -1994,7 +2014,6 @@ static void gfx_v8_0_gpu_init(struct amdgpu_device *adev) case 0xcc: /* B10 */ adev->gfx.config.max_cu_per_sh = 8; - adev->gfx.config.max_backends_per_se = 2; break; case 0xc5: case 0x81: @@ -2003,14 +2022,12 @@ static void gfx_v8_0_gpu_init(struct amdgpu_device *adev) case 0xcd: /* B8 */ adev->gfx.config.max_cu_per_sh = 6; - adev->gfx.config.max_backends_per_se = 2; break; case 0xc6: case 0xca: case 0xce: /* B6 */ adev->gfx.config.max_cu_per_sh = 6; - adev->gfx.config.max_backends_per_se = 2; break; case 0xc7: case 0x87: @@ -2018,7 +2035,6 @@ static void gfx_v8_0_gpu_init(struct amdgpu_device *adev) default: /* B4 */ adev->gfx.config.max_cu_per_sh = 4; - adev->gfx.config.max_backends_per_se = 1; break; } @@ -2278,7 +2294,6 @@ static int gfx_v8_0_rlc_load_microcode(struct amdgpu_device *adev) hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data; amdgpu_ucode_print_rlc_hdr(&hdr->header); - adev->gfx.rlc_fw_version = le32_to_cpu(hdr->header.ucode_version); fw_data = (const __le32 *)(adev->gfx.rlc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); @@ -2364,12 +2379,6 @@ static int gfx_v8_0_cp_gfx_load_microcode(struct amdgpu_device *adev) amdgpu_ucode_print_gfx_hdr(&pfp_hdr->header); amdgpu_ucode_print_gfx_hdr(&ce_hdr->header); amdgpu_ucode_print_gfx_hdr(&me_hdr->header); - adev->gfx.pfp_fw_version = le32_to_cpu(pfp_hdr->header.ucode_version); - adev->gfx.ce_fw_version = le32_to_cpu(ce_hdr->header.ucode_version); - adev->gfx.me_fw_version = le32_to_cpu(me_hdr->header.ucode_version); - adev->gfx.me_feature_version = le32_to_cpu(me_hdr->ucode_feature_version); - adev->gfx.ce_feature_version = le32_to_cpu(ce_hdr->ucode_feature_version); - adev->gfx.pfp_feature_version = le32_to_cpu(pfp_hdr->ucode_feature_version); gfx_v8_0_cp_gfx_enable(adev, false); @@ -2625,7 +2634,6 @@ static int gfx_v8_0_cp_compute_load_microcode(struct amdgpu_device *adev) mec_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data; amdgpu_ucode_print_gfx_hdr(&mec_hdr->header); - adev->gfx.mec_fw_version = le32_to_cpu(mec_hdr->header.ucode_version); fw_data = (const __le32 *) (adev->gfx.mec_fw->data + @@ -2644,7 +2652,6 @@ static int gfx_v8_0_cp_compute_load_microcode(struct amdgpu_device *adev) mec2_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec2_fw->data; amdgpu_ucode_print_gfx_hdr(&mec2_hdr->header); - adev->gfx.mec2_fw_version = le32_to_cpu(mec2_hdr->header.ucode_version); fw_data = (const __le32 *) (adev->gfx.mec2_fw->data + @@ -3756,7 +3763,7 @@ static void gfx_v8_0_ring_emit_hdp_flush(struct amdgpu_ring *ring) amdgpu_ring_write(ring, 0x20); /* poll interval */ } -static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring, +static void gfx_v8_0_ring_emit_ib_gfx(struct amdgpu_ring *ring, struct amdgpu_ib *ib) { bool need_ctx_switch = ring->current_ctx != ib->ctx; @@ -3764,15 +3771,10 @@ static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring, u32 next_rptr = ring->wptr + 5; /* drop the CE preamble IB for the same context */ - if ((ring->type == AMDGPU_RING_TYPE_GFX) && - (ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && - !need_ctx_switch) + if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && !need_ctx_switch) return; - if (ring->type == AMDGPU_RING_TYPE_COMPUTE) - control |= INDIRECT_BUFFER_VALID; - - if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) + if (need_ctx_switch) next_rptr += 2; next_rptr += 4; @@ -3783,7 +3785,7 @@ static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring, amdgpu_ring_write(ring, next_rptr); /* insert SWITCH_BUFFER packet before first IB in the ring frame */ - if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) { + if (need_ctx_switch) { amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); amdgpu_ring_write(ring, 0); } @@ -3806,6 +3808,36 @@ static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring, amdgpu_ring_write(ring, control); } +static void gfx_v8_0_ring_emit_ib_compute(struct amdgpu_ring *ring, + struct amdgpu_ib *ib) +{ + u32 header, control = 0; + u32 next_rptr = ring->wptr + 5; + + control |= INDIRECT_BUFFER_VALID; + + next_rptr += 4; + amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); + amdgpu_ring_write(ring, WRITE_DATA_DST_SEL(5) | WR_CONFIRM); + amdgpu_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); + amdgpu_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xffffffff); + amdgpu_ring_write(ring, next_rptr); + + header = PACKET3(PACKET3_INDIRECT_BUFFER, 2); + + control |= ib->length_dw | + (ib->vm ? (ib->vm->ids[ring->idx].id << 24) : 0); + + amdgpu_ring_write(ring, header); + amdgpu_ring_write(ring, +#ifdef __BIG_ENDIAN + (2 << 0) | +#endif + (ib->gpu_addr & 0xFFFFFFFC)); + amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFFFF); + amdgpu_ring_write(ring, control); +} + static void gfx_v8_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr, u64 seq, unsigned flags) { @@ -4227,7 +4259,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = { .get_wptr = gfx_v8_0_ring_get_wptr_gfx, .set_wptr = gfx_v8_0_ring_set_wptr_gfx, .parse_cs = NULL, - .emit_ib = gfx_v8_0_ring_emit_ib, + .emit_ib = gfx_v8_0_ring_emit_ib_gfx, .emit_fence = gfx_v8_0_ring_emit_fence_gfx, .emit_semaphore = gfx_v8_0_ring_emit_semaphore, .emit_vm_flush = gfx_v8_0_ring_emit_vm_flush, @@ -4243,7 +4275,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = { .get_wptr = gfx_v8_0_ring_get_wptr_compute, .set_wptr = gfx_v8_0_ring_set_wptr_compute, .parse_cs = NULL, - .emit_ib = gfx_v8_0_ring_emit_ib, + .emit_ib = gfx_v8_0_ring_emit_ib_compute, .emit_fence = gfx_v8_0_ring_emit_fence_compute, .emit_semaphore = gfx_v8_0_ring_emit_semaphore, .emit_vm_flush = gfx_v8_0_ring_emit_vm_flush, diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c index d7895885fe0c..a988dfb1d394 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c @@ -121,6 +121,7 @@ static int sdma_v2_4_init_microcode(struct amdgpu_device *adev) int err, i; struct amdgpu_firmware_info *info = NULL; const struct common_firmware_header *header = NULL; + const struct sdma_firmware_header_v1_0 *hdr; DRM_DEBUG("\n"); @@ -142,6 +143,9 @@ static int sdma_v2_4_init_microcode(struct amdgpu_device *adev) err = amdgpu_ucode_validate(adev->sdma[i].fw); if (err) goto out; + hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma[i].fw->data; + adev->sdma[i].fw_version = le32_to_cpu(hdr->header.ucode_version); + adev->sdma[i].feature_version = le32_to_cpu(hdr->ucode_feature_version); if (adev->firmware.smu_load) { info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA0 + i]; @@ -541,8 +545,6 @@ static int sdma_v2_4_load_microcode(struct amdgpu_device *adev) hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma[i].fw->data; amdgpu_ucode_print_sdma_hdr(&hdr->header); fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4; - adev->sdma[i].fw_version = le32_to_cpu(hdr->header.ucode_version); - fw_data = (const __le32 *) (adev->sdma[i].fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index 7bb37b93993f..2b86569b18d3 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -159,6 +159,7 @@ static int sdma_v3_0_init_microcode(struct amdgpu_device *adev) int err, i; struct amdgpu_firmware_info *info = NULL; const struct common_firmware_header *header = NULL; + const struct sdma_firmware_header_v1_0 *hdr; DRM_DEBUG("\n"); @@ -183,6 +184,9 @@ static int sdma_v3_0_init_microcode(struct amdgpu_device *adev) err = amdgpu_ucode_validate(adev->sdma[i].fw); if (err) goto out; + hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma[i].fw->data; + adev->sdma[i].fw_version = le32_to_cpu(hdr->header.ucode_version); + adev->sdma[i].feature_version = le32_to_cpu(hdr->ucode_feature_version); if (adev->firmware.smu_load) { info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA0 + i]; @@ -630,8 +634,6 @@ static int sdma_v3_0_load_microcode(struct amdgpu_device *adev) hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma[i].fw->data; amdgpu_ucode_print_sdma_hdr(&hdr->header); fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4; - adev->sdma[i].fw_version = le32_to_cpu(hdr->header.ucode_version); - fw_data = (const __le32 *) (adev->sdma[i].fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index d62c4002e39c..d1064ca3670e 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -35,6 +35,8 @@ #include "oss/oss_2_0_d.h" #include "oss/oss_2_0_sh_mask.h" #include "gca/gfx_8_0_d.h" +#include "smu/smu_7_1_2_d.h" +#include "smu/smu_7_1_2_sh_mask.h" #define GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT 0x04 #define GRBM_GFX_INDEX__VCE_INSTANCE_MASK 0x10 @@ -112,6 +114,10 @@ static int vce_v3_0_start(struct amdgpu_device *adev) mutex_lock(&adev->grbm_idx_mutex); for (idx = 0; idx < 2; ++idx) { + + if (adev->vce.harvest_config & (1 << idx)) + continue; + if(idx == 0) WREG32_P(mmGRBM_GFX_INDEX, 0, ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK); @@ -190,10 +196,52 @@ static int vce_v3_0_start(struct amdgpu_device *adev) return 0; } +#define ixVCE_HARVEST_FUSE_MACRO__ADDRESS 0xC0014074 +#define VCE_HARVEST_FUSE_MACRO__SHIFT 27 +#define VCE_HARVEST_FUSE_MACRO__MASK 0x18000000 + +static unsigned vce_v3_0_get_harvest_config(struct amdgpu_device *adev) +{ + u32 tmp; + unsigned ret; + + if (adev->flags & AMDGPU_IS_APU) + tmp = (RREG32_SMC(ixVCE_HARVEST_FUSE_MACRO__ADDRESS) & + VCE_HARVEST_FUSE_MACRO__MASK) >> + VCE_HARVEST_FUSE_MACRO__SHIFT; + else + tmp = (RREG32_SMC(ixCC_HARVEST_FUSES) & + CC_HARVEST_FUSES__VCE_DISABLE_MASK) >> + CC_HARVEST_FUSES__VCE_DISABLE__SHIFT; + + switch (tmp) { + case 1: + ret = AMDGPU_VCE_HARVEST_VCE0; + break; + case 2: + ret = AMDGPU_VCE_HARVEST_VCE1; + break; + case 3: + ret = AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1; + break; + default: + ret = 0; + } + + return ret; +} + static int vce_v3_0_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + adev->vce.harvest_config = vce_v3_0_get_harvest_config(adev); + + if ((adev->vce.harvest_config & + (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1)) == + (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1)) + return -ENOENT; + vce_v3_0_set_ring_funcs(adev); vce_v3_0_set_irq_funcs(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index fa5a4448531d..68552da40287 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -122,6 +122,32 @@ static void vi_smc_wreg(struct amdgpu_device *adev, u32 reg, u32 v) spin_unlock_irqrestore(&adev->smc_idx_lock, flags); } +/* smu_8_0_d.h */ +#define mmMP0PUB_IND_INDEX 0x180 +#define mmMP0PUB_IND_DATA 0x181 + +static u32 cz_smc_rreg(struct amdgpu_device *adev, u32 reg) +{ + unsigned long flags; + u32 r; + + spin_lock_irqsave(&adev->smc_idx_lock, flags); + WREG32(mmMP0PUB_IND_INDEX, (reg)); + r = RREG32(mmMP0PUB_IND_DATA); + spin_unlock_irqrestore(&adev->smc_idx_lock, flags); + return r; +} + +static void cz_smc_wreg(struct amdgpu_device *adev, u32 reg, u32 v) +{ + unsigned long flags; + + spin_lock_irqsave(&adev->smc_idx_lock, flags); + WREG32(mmMP0PUB_IND_INDEX, (reg)); + WREG32(mmMP0PUB_IND_DATA, (v)); + spin_unlock_irqrestore(&adev->smc_idx_lock, flags); +} + static u32 vi_uvd_ctx_rreg(struct amdgpu_device *adev, u32 reg) { unsigned long flags; @@ -1222,8 +1248,13 @@ static int vi_common_early_init(void *handle) bool smc_enabled = false; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - adev->smc_rreg = &vi_smc_rreg; - adev->smc_wreg = &vi_smc_wreg; + if (adev->flags & AMDGPU_IS_APU) { + adev->smc_rreg = &cz_smc_rreg; + adev->smc_wreg = &cz_smc_wreg; + } else { + adev->smc_rreg = &vi_smc_rreg; + adev->smc_wreg = &vi_smc_wreg; + } adev->pcie_rreg = &vi_pcie_rreg; adev->pcie_wreg = &vi_pcie_wreg; adev->uvd_ctx_rreg = &vi_uvd_ctx_rreg; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 8a1f999daa24..9be007081b72 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -420,6 +420,12 @@ void kfd_unbind_process_from_device(struct kfd_dev *dev, unsigned int pasid) pqm_uninit(&p->pqm); pdd = kfd_get_process_device_data(dev, p); + + if (!pdd) { + mutex_unlock(&p->mutex); + return; + } + if (pdd->reset_wavefronts) { dbgdev_wave_reset_wavefronts(pdd->dev, p); pdd->reset_wavefronts = false; @@ -431,8 +437,7 @@ void kfd_unbind_process_from_device(struct kfd_dev *dev, unsigned int pasid) * We don't call amd_iommu_unbind_pasid() here * because the IOMMU called us. */ - if (pdd) - pdd->bound = false; + pdd->bound = false; mutex_unlock(&p->mutex); } diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 42d2ffa08716..01ffe9bffe38 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -531,8 +531,6 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc, drm_crtc_vblank_off(crtc); - crtc->mode = *adj; - val = dcrtc->dumb_ctrl & ~CFG_DUMB_ENA; if (val != dcrtc->dumb_ctrl) { dcrtc->dumb_ctrl = val; diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c index 580e10acaa3a..60a688ef81c7 100644 --- a/drivers/gpu/drm/armada/armada_gem.c +++ b/drivers/gpu/drm/armada/armada_gem.c @@ -69,8 +69,9 @@ void armada_gem_free_object(struct drm_gem_object *obj) if (dobj->obj.import_attach) { /* We only ever display imported data */ - dma_buf_unmap_attachment(dobj->obj.import_attach, dobj->sgt, - DMA_TO_DEVICE); + if (dobj->sgt) + dma_buf_unmap_attachment(dobj->obj.import_attach, + dobj->sgt, DMA_TO_DEVICE); drm_prime_gem_destroy(&dobj->obj, NULL); } diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index c5b06fdb459c..e939faba7fcc 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -7,6 +7,7 @@ * published by the Free Software Foundation. */ #include <drm/drmP.h> +#include <drm/drm_plane_helper.h> #include "armada_crtc.h" #include "armada_drm.h" #include "armada_fb.h" @@ -85,16 +86,8 @@ static void armada_plane_vbl(struct armada_crtc *dcrtc, void *data) if (fb) armada_drm_queue_unref_work(dcrtc->crtc.dev, fb); -} -static unsigned armada_limit(int start, unsigned size, unsigned max) -{ - int end = start + size; - if (end < 0) - return 0; - if (start < 0) - start = 0; - return (unsigned)end > max ? max - start : end - start; + wake_up(&dplane->vbl.wait); } static int @@ -105,26 +98,39 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, { struct armada_plane *dplane = drm_to_armada_plane(plane); struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); + struct drm_rect src = { + .x1 = src_x, + .y1 = src_y, + .x2 = src_x + src_w, + .y2 = src_y + src_h, + }; + struct drm_rect dest = { + .x1 = crtc_x, + .y1 = crtc_y, + .x2 = crtc_x + crtc_w, + .y2 = crtc_y + crtc_h, + }; + const struct drm_rect clip = { + .x2 = crtc->mode.hdisplay, + .y2 = crtc->mode.vdisplay, + }; uint32_t val, ctrl0; unsigned idx = 0; + bool visible; int ret; - crtc_w = armada_limit(crtc_x, crtc_w, dcrtc->crtc.mode.hdisplay); - crtc_h = armada_limit(crtc_y, crtc_h, dcrtc->crtc.mode.vdisplay); + ret = drm_plane_helper_check_update(plane, crtc, fb, &src, &dest, &clip, + 0, INT_MAX, true, false, &visible); + if (ret) + return ret; + ctrl0 = CFG_DMA_FMT(drm_fb_to_armada_fb(fb)->fmt) | CFG_DMA_MOD(drm_fb_to_armada_fb(fb)->mod) | CFG_CBSH_ENA | CFG_DMA_HSMOOTH | CFG_DMA_ENA; /* Does the position/size result in nothing to display? */ - if (crtc_w == 0 || crtc_h == 0) { + if (!visible) ctrl0 &= ~CFG_DMA_ENA; - } - - /* - * FIXME: if the starting point is off screen, we need to - * adjust src_x, src_y, src_w, src_h appropriately, and - * according to the scale. - */ if (!dcrtc->plane) { dcrtc->plane = plane; @@ -134,15 +140,19 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, /* FIXME: overlay on an interlaced display */ /* Just updating the position/size? */ if (plane->fb == fb && dplane->ctrl0 == ctrl0) { - val = (src_h & 0xffff0000) | src_w >> 16; + val = (drm_rect_height(&src) & 0xffff0000) | + drm_rect_width(&src) >> 16; dplane->src_hw = val; writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_HPXL_VLN); - val = crtc_h << 16 | crtc_w; + + val = drm_rect_height(&dest) << 16 | drm_rect_width(&dest); dplane->dst_hw = val; writel_relaxed(val, dcrtc->base + LCD_SPU_DZM_HPXL_VLN); - val = crtc_y << 16 | crtc_x; + + val = dest.y1 << 16 | dest.x1; dplane->dst_yx = val; writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_OVSA_HPXL_VLN); + return 0; } else if (~dplane->ctrl0 & ctrl0 & CFG_DMA_ENA) { /* Power up the Y/U/V FIFOs on ENA 0->1 transitions */ @@ -150,15 +160,14 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, dcrtc->base + LCD_SPU_SRAM_PARA1); } - ret = wait_event_timeout(dplane->vbl.wait, - list_empty(&dplane->vbl.update.node), - HZ/25); - if (ret < 0) - return ret; + wait_event_timeout(dplane->vbl.wait, + list_empty(&dplane->vbl.update.node), + HZ/25); if (plane->fb != fb) { struct armada_gem_object *obj = drm_fb_obj(fb); - uint32_t sy, su, sv; + uint32_t addr[3], pixel_format; + int i, num_planes, hsub; /* * Take a reference on the new framebuffer - we want to @@ -178,26 +187,39 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, older_fb); } - src_y >>= 16; - src_x >>= 16; - sy = obj->dev_addr + fb->offsets[0] + src_y * fb->pitches[0] + - src_x * fb->bits_per_pixel / 8; - su = obj->dev_addr + fb->offsets[1] + src_y * fb->pitches[1] + - src_x; - sv = obj->dev_addr + fb->offsets[2] + src_y * fb->pitches[2] + - src_x; + src_y = src.y1 >> 16; + src_x = src.x1 >> 16; - armada_reg_queue_set(dplane->vbl.regs, idx, sy, + pixel_format = fb->pixel_format; + hsub = drm_format_horz_chroma_subsampling(pixel_format); + num_planes = drm_format_num_planes(pixel_format); + + /* + * Annoyingly, shifting a YUYV-format image by one pixel + * causes the U/V planes to toggle. Toggle the UV swap. + * (Unfortunately, this causes momentary colour flickering.) + */ + if (src_x & (hsub - 1) && num_planes == 1) + ctrl0 ^= CFG_DMA_MOD(CFG_SWAPUV); + + for (i = 0; i < num_planes; i++) + addr[i] = obj->dev_addr + fb->offsets[i] + + src_y * fb->pitches[i] + + src_x * drm_format_plane_cpp(pixel_format, i); + for (; i < ARRAY_SIZE(addr); i++) + addr[i] = 0; + + armada_reg_queue_set(dplane->vbl.regs, idx, addr[0], LCD_SPU_DMA_START_ADDR_Y0); - armada_reg_queue_set(dplane->vbl.regs, idx, su, + armada_reg_queue_set(dplane->vbl.regs, idx, addr[1], LCD_SPU_DMA_START_ADDR_U0); - armada_reg_queue_set(dplane->vbl.regs, idx, sv, + armada_reg_queue_set(dplane->vbl.regs, idx, addr[2], LCD_SPU_DMA_START_ADDR_V0); - armada_reg_queue_set(dplane->vbl.regs, idx, sy, + armada_reg_queue_set(dplane->vbl.regs, idx, addr[0], LCD_SPU_DMA_START_ADDR_Y1); - armada_reg_queue_set(dplane->vbl.regs, idx, su, + armada_reg_queue_set(dplane->vbl.regs, idx, addr[1], LCD_SPU_DMA_START_ADDR_U1); - armada_reg_queue_set(dplane->vbl.regs, idx, sv, + armada_reg_queue_set(dplane->vbl.regs, idx, addr[2], LCD_SPU_DMA_START_ADDR_V1); val = fb->pitches[0] << 16 | fb->pitches[0]; @@ -208,24 +230,27 @@ armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, LCD_SPU_DMA_PITCH_UV); } - val = (src_h & 0xffff0000) | src_w >> 16; + val = (drm_rect_height(&src) & 0xffff0000) | drm_rect_width(&src) >> 16; if (dplane->src_hw != val) { dplane->src_hw = val; armada_reg_queue_set(dplane->vbl.regs, idx, val, LCD_SPU_DMA_HPXL_VLN); } - val = crtc_h << 16 | crtc_w; + + val = drm_rect_height(&dest) << 16 | drm_rect_width(&dest); if (dplane->dst_hw != val) { dplane->dst_hw = val; armada_reg_queue_set(dplane->vbl.regs, idx, val, LCD_SPU_DZM_HPXL_VLN); } - val = crtc_y << 16 | crtc_x; + + val = dest.y1 << 16 | dest.x1; if (dplane->dst_yx != val) { dplane->dst_yx = val; armada_reg_queue_set(dplane->vbl.regs, idx, val, LCD_SPU_DMA_OVSA_HPXL_VLN); } + if (dplane->ctrl0 != ctrl0) { dplane->ctrl0 = ctrl0; armada_reg_queue_mod(dplane->vbl.regs, idx, ctrl0, @@ -279,7 +304,11 @@ static int armada_plane_disable(struct drm_plane *plane) static void armada_plane_destroy(struct drm_plane *plane) { - kfree(plane); + struct armada_plane *dplane = drm_to_armada_plane(plane); + + drm_plane_cleanup(plane); + + kfree(dplane); } static int armada_plane_set_property(struct drm_plane *plane, diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index f69b92535505..5ae5c6923128 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -355,6 +355,7 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev) planes->overlays[i]->base.possible_crtcs = 1 << crtc->id; drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs); + drm_crtc_vblank_reset(&crtc->base); dc->crtc = &crtc->base; diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index 60b0c13d7ff5..6fad1f9648f3 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -313,20 +313,20 @@ static int atmel_hlcdc_dc_load(struct drm_device *dev) pm_runtime_enable(dev->dev); - ret = atmel_hlcdc_dc_modeset_init(dev); + ret = drm_vblank_init(dev, 1); if (ret < 0) { - dev_err(dev->dev, "failed to initialize mode setting\n"); + dev_err(dev->dev, "failed to initialize vblank\n"); goto err_periph_clk_disable; } - drm_mode_config_reset(dev); - - ret = drm_vblank_init(dev, 1); + ret = atmel_hlcdc_dc_modeset_init(dev); if (ret < 0) { - dev_err(dev->dev, "failed to initialize vblank\n"); + dev_err(dev->dev, "failed to initialize mode setting\n"); goto err_periph_clk_disable; } + drm_mode_config_reset(dev); + pm_runtime_get_sync(dev->dev); ret = drm_irq_install(dev, dc->hlcdc->irq); pm_runtime_put_sync(dev->dev); diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 5b59d5ad7d1c..9dcc7280e572 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -196,7 +196,12 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx) } funcs = connector->helper_private; - new_encoder = funcs->best_encoder(connector); + + if (funcs->atomic_best_encoder) + new_encoder = funcs->atomic_best_encoder(connector, + connector_state); + else + new_encoder = funcs->best_encoder(connector); if (!new_encoder) { DRM_DEBUG_ATOMIC("No suitable encoder found for [CONNECTOR:%d:%s]\n", @@ -229,6 +234,9 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx) } } + if (WARN_ON(!connector_state->crtc)) + return -EINVAL; + connector_state->best_encoder = new_encoder; idx = drm_crtc_index(connector_state->crtc); diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index b9ba06176eb1..fed748311b92 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2706,8 +2706,11 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; - /* For some reason crtc x/y offsets are signed internally. */ - if (crtc_req->x > INT_MAX || crtc_req->y > INT_MAX) + /* + * Universal plane src offsets are only 16.16, prevent havoc for + * drivers using universal plane code internally. + */ + if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000) return -ERANGE; drm_modeset_lock_all(dev); @@ -5395,12 +5398,9 @@ void drm_mode_config_reset(struct drm_device *dev) if (encoder->funcs->reset) encoder->funcs->reset(encoder); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - connector->status = connector_status_unknown; - + list_for_each_entry(connector, &dev->mode_config.connector_list, head) if (connector->funcs->reset) connector->funcs->reset(connector); - } } EXPORT_SYMBOL(drm_mode_config_reset); diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 778bbb6425b8..b0487c9f018c 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -1294,7 +1294,6 @@ retry: goto retry; } DRM_DEBUG_KMS("failed to dpcd write %d %d\n", tosend, ret); - WARN(1, "fail\n"); return -EIO; } diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c index aa8bbb460c57..9cfcd0aef0df 100644 --- a/drivers/gpu/drm/drm_ioc32.c +++ b/drivers/gpu/drm/drm_ioc32.c @@ -70,6 +70,8 @@ #define DRM_IOCTL_WAIT_VBLANK32 DRM_IOWR(0x3a, drm_wait_vblank32_t) +#define DRM_IOCTL_MODE_ADDFB232 DRM_IOWR(0xb8, drm_mode_fb_cmd232_t) + typedef struct drm_version_32 { int version_major; /**< Major version */ int version_minor; /**< Minor version */ @@ -1016,6 +1018,63 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd, return 0; } +typedef struct drm_mode_fb_cmd232 { + u32 fb_id; + u32 width; + u32 height; + u32 pixel_format; + u32 flags; + u32 handles[4]; + u32 pitches[4]; + u32 offsets[4]; + u64 modifier[4]; +} __attribute__((packed)) drm_mode_fb_cmd232_t; + +static int compat_drm_mode_addfb2(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct drm_mode_fb_cmd232 __user *argp = (void __user *)arg; + struct drm_mode_fb_cmd232 req32; + struct drm_mode_fb_cmd2 __user *req64; + int i; + int err; + + if (copy_from_user(&req32, argp, sizeof(req32))) + return -EFAULT; + + req64 = compat_alloc_user_space(sizeof(*req64)); + + if (!access_ok(VERIFY_WRITE, req64, sizeof(*req64)) + || __put_user(req32.width, &req64->width) + || __put_user(req32.height, &req64->height) + || __put_user(req32.pixel_format, &req64->pixel_format) + || __put_user(req32.flags, &req64->flags)) + return -EFAULT; + + for (i = 0; i < 4; i++) { + if (__put_user(req32.handles[i], &req64->handles[i])) + return -EFAULT; + if (__put_user(req32.pitches[i], &req64->pitches[i])) + return -EFAULT; + if (__put_user(req32.offsets[i], &req64->offsets[i])) + return -EFAULT; + if (__put_user(req32.modifier[i], &req64->modifier[i])) + return -EFAULT; + } + + err = drm_ioctl(file, DRM_IOCTL_MODE_ADDFB2, (unsigned long)req64); + if (err) + return err; + + if (__get_user(req32.fb_id, &req64->fb_id)) + return -EFAULT; + + if (copy_to_user(argp, &req32, sizeof(req32))) + return -EFAULT; + + return 0; +} + static drm_ioctl_compat_t *drm_compat_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_VERSION32)] = compat_drm_version, [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE32)] = compat_drm_getunique, @@ -1048,6 +1107,7 @@ static drm_ioctl_compat_t *drm_compat_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW32)] = compat_drm_update_draw, #endif [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK32)] = compat_drm_wait_vblank, + [DRM_IOCTL_NR(DRM_IOCTL_MODE_ADDFB232)] = compat_drm_mode_addfb2, }; /** diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index f9cc68fbd2a3..b50fa0afd907 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -75,7 +75,7 @@ module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600) module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600); static void store_vblank(struct drm_device *dev, int crtc, - unsigned vblank_count_inc, + u32 vblank_count_inc, struct timeval *t_vblank) { struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index fe1599d75f14..424228be79ae 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -606,8 +606,6 @@ static void tda998x_write_if(struct tda998x_priv *priv, uint8_t bit, uint16_t addr, uint8_t *buf, size_t size) { - buf[PB(0)] = tda998x_cksum(buf, size); - reg_clear(priv, REG_DIP_IF_FLAGS, bit); reg_write_range(priv, addr, buf, size); reg_set(priv, REG_DIP_IF_FLAGS, bit); @@ -627,6 +625,8 @@ tda998x_write_aif(struct tda998x_priv *priv, struct tda998x_encoder_params *p) buf[PB(4)] = p->audio_frame[4]; buf[PB(5)] = p->audio_frame[5] & 0xf8; /* DM_INH + LSV */ + buf[PB(0)] = tda998x_cksum(buf, sizeof(buf)); + tda998x_write_if(priv, DIP_IF_FLAGS_IF4, REG_IF4_HB0, buf, sizeof(buf)); } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 542fac628b28..fd1de451c8c6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -826,6 +826,7 @@ struct intel_context { struct kref ref; int user_handle; uint8_t remap_slice; + struct drm_i915_private *i915; struct drm_i915_file_private *file_priv; struct i915_ctx_hang_stats hang_stats; struct i915_hw_ppgtt *ppgtt; @@ -2036,8 +2037,6 @@ struct drm_i915_gem_object { unsigned int cache_level:3; unsigned int cache_dirty:1; - unsigned int has_dma_mapping:1; - unsigned int frontbuffer_bits:INTEL_FRONTBUFFER_BITS; unsigned int pin_display; @@ -3116,7 +3115,8 @@ void i915_debugfs_cleanup(struct drm_minor *minor); int i915_debugfs_connector_add(struct drm_connector *connector); void intel_display_crc_init(struct drm_device *dev); #else -static inline int i915_debugfs_connector_add(struct drm_connector *connector) {} +static inline int i915_debugfs_connector_add(struct drm_connector *connector) +{ return 0; } static inline void intel_display_crc_init(struct drm_device *dev) {} #endif @@ -3303,15 +3303,14 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val); #define I915_READ64(reg) dev_priv->uncore.funcs.mmio_readq(dev_priv, (reg), true) #define I915_READ64_2x32(lower_reg, upper_reg) ({ \ - u32 upper = I915_READ(upper_reg); \ - u32 lower = I915_READ(lower_reg); \ - u32 tmp = I915_READ(upper_reg); \ - if (upper != tmp) { \ - upper = tmp; \ - lower = I915_READ(lower_reg); \ - WARN_ON(I915_READ(upper_reg) != upper); \ - } \ - (u64)upper << 32 | lower; }) + u32 upper, lower, tmp; \ + tmp = I915_READ(upper_reg); \ + do { \ + upper = tmp; \ + lower = I915_READ(lower_reg); \ + tmp = I915_READ(upper_reg); \ + } while (upper != tmp); \ + (u64)upper << 32 | lower; }) #define POSTING_READ(reg) (void)I915_READ_NOTRACE(reg) #define POSTING_READ16(reg) (void)I915_READ16_NOTRACE(reg) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 248fd1ac7b3a..52b446b27b4d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -213,7 +213,6 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj) sg_dma_len(sg) = obj->base.size; obj->pages = st; - obj->has_dma_mapping = true; return 0; } @@ -265,8 +264,6 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj) sg_free_table(obj->pages); kfree(obj->pages); - - obj->has_dma_mapping = false; } static void @@ -2139,6 +2136,8 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj) obj->base.read_domains = obj->base.write_domain = I915_GEM_DOMAIN_CPU; } + i915_gem_gtt_finish_object(obj); + if (i915_gem_object_needs_bit17_swizzle(obj)) i915_gem_object_save_bit_17_swizzle(obj); @@ -2199,6 +2198,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) struct sg_page_iter sg_iter; struct page *page; unsigned long last_pfn = 0; /* suppress gcc warning */ + int ret; gfp_t gfp; /* Assert that the object is not currently in any GPU domain. As it @@ -2246,8 +2246,10 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) */ i915_gem_shrink_all(dev_priv); page = shmem_read_mapping_page(mapping, i); - if (IS_ERR(page)) + if (IS_ERR(page)) { + ret = PTR_ERR(page); goto err_pages; + } } #ifdef CONFIG_SWIOTLB if (swiotlb_nr_tbl()) { @@ -2276,6 +2278,10 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) sg_mark_end(sg); obj->pages = st; + ret = i915_gem_gtt_prepare_object(obj); + if (ret) + goto err_pages; + if (i915_gem_object_needs_bit17_swizzle(obj)) i915_gem_object_do_bit_17_swizzle(obj); @@ -2300,10 +2306,10 @@ err_pages: * space and so want to translate the error from shmemfs back to our * usual understanding of ENOMEM. */ - if (PTR_ERR(page) == -ENOSPC) - return -ENOMEM; - else - return PTR_ERR(page); + if (ret == -ENOSPC) + ret = -ENOMEM; + + return ret; } /* Ensure that the associated pages are gathered from the backing storage @@ -2542,6 +2548,7 @@ int __i915_add_request(struct intel_engine_cs *ring, } request->emitted_jiffies = jiffies; + ring->last_submitted_seqno = request->seqno; list_add_tail(&request->list, &ring->request_list); request->file_priv = NULL; @@ -3247,10 +3254,8 @@ int i915_vma_unbind(struct i915_vma *vma) /* Since the unbound list is global, only move to that list if * no more VMAs exist. */ - if (list_empty(&obj->vma_list)) { - i915_gem_gtt_finish_object(obj); + if (list_empty(&obj->vma_list)) list_move_tail(&obj->global_list, &dev_priv->mm.unbound_list); - } /* And finally now the object is completely decoupled from this vma, * we can drop its hold on the backing storage and allow it to be @@ -3768,22 +3773,16 @@ search_free: goto err_remove_node; } - ret = i915_gem_gtt_prepare_object(obj); - if (ret) - goto err_remove_node; - trace_i915_vma_bind(vma, flags); ret = i915_vma_bind(vma, obj->cache_level, flags); if (ret) - goto err_finish_gtt; + goto err_remove_node; list_move_tail(&obj->global_list, &dev_priv->mm.bound_list); list_add_tail(&vma->mm_list, &vm->inactive_list); return vma; -err_finish_gtt: - i915_gem_gtt_finish_object(obj); err_remove_node: drm_mm_remove_node(&vma->node); err_free_vma: diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 8867818b1401..48afa777e94a 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -135,8 +135,7 @@ static int get_context_size(struct drm_device *dev) void i915_gem_context_free(struct kref *ctx_ref) { - struct intel_context *ctx = container_of(ctx_ref, - typeof(*ctx), ref); + struct intel_context *ctx = container_of(ctx_ref, typeof(*ctx), ref); trace_i915_context_free(ctx); @@ -157,9 +156,7 @@ i915_gem_alloc_context_obj(struct drm_device *dev, size_t size) struct drm_i915_gem_object *obj; int ret; - obj = i915_gem_object_create_stolen(dev, size); - if (obj == NULL) - obj = i915_gem_alloc_object(dev, size); + obj = i915_gem_alloc_object(dev, size); if (obj == NULL) return ERR_PTR(-ENOMEM); @@ -197,6 +194,7 @@ __create_hw_context(struct drm_device *dev, kref_init(&ctx->ref); list_add_tail(&ctx->link, &dev_priv->context_list); + ctx->i915 = dev_priv; if (dev_priv->hw_context_size) { struct drm_i915_gem_object *obj = diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index 7998da27c500..e9c2bfd85b52 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c @@ -256,7 +256,6 @@ static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj) return PTR_ERR(sg); obj->pages = sg; - obj->has_dma_mapping = true; return 0; } @@ -264,7 +263,6 @@ static void i915_gem_object_put_pages_dmabuf(struct drm_i915_gem_object *obj) { dma_buf_unmap_attachment(obj->base.import_attach, obj->pages, DMA_BIDIRECTIONAL); - obj->has_dma_mapping = false; } static const struct drm_i915_gem_object_ops i915_gem_object_dmabuf_ops = { diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 9daa2883ac18..31e8269e6e3d 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1723,9 +1723,6 @@ void i915_gem_suspend_gtt_mappings(struct drm_device *dev) int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj) { - if (obj->has_dma_mapping) - return 0; - if (!dma_map_sg(&obj->base.dev->pdev->dev, obj->pages->sgl, obj->pages->nents, PCI_DMA_BIDIRECTIONAL)) @@ -1926,6 +1923,17 @@ static int ggtt_bind_vma(struct i915_vma *vma, vma->vm->insert_entries(vma->vm, pages, vma->node.start, cache_level, pte_flags); + + /* Note the inconsistency here is due to absence of the + * aliasing ppgtt on gen4 and earlier. Though we always + * request PIN_USER for execbuffer (translated to LOCAL_BIND), + * without the appgtt, we cannot honour that request and so + * must substitute it with a global binding. Since we do this + * behind the upper layers back, we need to explicitly set + * the bound flag ourselves. + */ + vma->bound |= GLOBAL_BIND; + } if (dev_priv->mm.aliasing_ppgtt && flags & LOCAL_BIND) { @@ -1972,10 +1980,8 @@ void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj) interruptible = do_idling(dev_priv); - if (!obj->has_dma_mapping) - dma_unmap_sg(&dev->pdev->dev, - obj->pages->sgl, obj->pages->nents, - PCI_DMA_BIDIRECTIONAL); + dma_unmap_sg(&dev->pdev->dev, obj->pages->sgl, obj->pages->nents, + PCI_DMA_BIDIRECTIONAL); undo_idling(dev_priv, interruptible); } @@ -2546,6 +2552,8 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj; struct i915_address_space *vm; + struct i915_vma *vma; + bool flush; i915_check_and_clear_faults(dev); @@ -2555,16 +2563,23 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) dev_priv->gtt.base.total, true); + /* Cache flush objects bound into GGTT and rebind them. */ + vm = &dev_priv->gtt.base; list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { - struct i915_vma *vma = i915_gem_obj_to_vma(obj, - &dev_priv->gtt.base); - if (!vma) - continue; + flush = false; + list_for_each_entry(vma, &obj->vma_list, vma_link) { + if (vma->vm != vm) + continue; - i915_gem_clflush_object(obj, obj->pin_display); - WARN_ON(i915_vma_bind(vma, obj->cache_level, PIN_UPDATE)); - } + WARN_ON(i915_vma_bind(vma, obj->cache_level, + PIN_UPDATE)); + flush = true; + } + + if (flush) + i915_gem_clflush_object(obj, obj->pin_display); + } if (INTEL_INFO(dev)->gen >= 8) { if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 348ed5abcdbf..8b5b784c62fe 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -416,7 +416,6 @@ _i915_gem_object_create_stolen(struct drm_device *dev, if (obj->pages == NULL) goto cleanup; - obj->has_dma_mapping = true; i915_gem_object_pin_pages(obj); obj->stolen = stolen; diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 633bd1fcab69..d19c9db5e18c 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -464,7 +464,10 @@ i915_gem_get_tiling(struct drm_device *dev, void *data, } /* Hide bit 17 from the user -- see comment in i915_gem_set_tiling */ - args->phys_swizzle_mode = args->swizzle_mode; + if (dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) + args->phys_swizzle_mode = I915_BIT_6_SWIZZLE_UNKNOWN; + else + args->phys_swizzle_mode = args->swizzle_mode; if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_17) args->swizzle_mode = I915_BIT_6_SWIZZLE_9; if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17) diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index 1f4e5a32a16e..8fd431bcdfd3 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -545,6 +545,26 @@ err: return ret; } +static int +__i915_gem_userptr_set_pages(struct drm_i915_gem_object *obj, + struct page **pvec, int num_pages) +{ + int ret; + + ret = st_set_pages(&obj->pages, pvec, num_pages); + if (ret) + return ret; + + ret = i915_gem_gtt_prepare_object(obj); + if (ret) { + sg_free_table(obj->pages); + kfree(obj->pages); + obj->pages = NULL; + } + + return ret; +} + static void __i915_gem_userptr_get_pages_worker(struct work_struct *_work) { @@ -584,9 +604,12 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) if (obj->userptr.work != &work->work) { ret = 0; } else if (pinned == num_pages) { - ret = st_set_pages(&obj->pages, pvec, num_pages); + ret = __i915_gem_userptr_set_pages(obj, pvec, num_pages); if (ret == 0) { list_add_tail(&obj->global_list, &to_i915(dev)->mm.unbound_list); + obj->get_page.sg = obj->pages->sgl; + obj->get_page.last = 0; + pinned = 0; } } @@ -693,7 +716,7 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) } } } else { - ret = st_set_pages(&obj->pages, pvec, num_pages); + ret = __i915_gem_userptr_set_pages(obj, pvec, num_pages); if (ret == 0) { obj->userptr.work = NULL; pinned = 0; @@ -715,6 +738,8 @@ i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj) if (obj->madv != I915_MADV_WILLNEED) obj->dirty = 0; + i915_gem_gtt_finish_object(obj); + for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) { struct page *page = sg_page_iter_page(&sg_iter); diff --git a/drivers/gpu/drm/i915/i915_ioc32.c b/drivers/gpu/drm/i915/i915_ioc32.c index 176de6322e4d..23aa04cded6b 100644 --- a/drivers/gpu/drm/i915/i915_ioc32.c +++ b/drivers/gpu/drm/i915/i915_ioc32.c @@ -204,7 +204,7 @@ long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) drm_ioctl_compat_t *fn = NULL; int ret; - if (nr < DRM_COMMAND_BASE) + if (nr < DRM_COMMAND_BASE || nr >= DRM_COMMAND_END) return drm_compat_ioctl(filp, cmd, arg); if (nr < DRM_COMMAND_BASE + ARRAY_SIZE(i915_compat_ioctls)) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index e6bb72dca3ff..984e2fe6688c 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2706,18 +2706,11 @@ static void gen8_disable_vblank(struct drm_device *dev, int pipe) spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } -static struct drm_i915_gem_request * -ring_last_request(struct intel_engine_cs *ring) -{ - return list_entry(ring->request_list.prev, - struct drm_i915_gem_request, list); -} - static bool -ring_idle(struct intel_engine_cs *ring) +ring_idle(struct intel_engine_cs *ring, u32 seqno) { return (list_empty(&ring->request_list) || - i915_gem_request_completed(ring_last_request(ring), false)); + i915_seqno_passed(seqno, ring->last_submitted_seqno)); } static bool @@ -2939,7 +2932,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) acthd = intel_ring_get_active_head(ring); if (ring->hangcheck.seqno == seqno) { - if (ring_idle(ring)) { + if (ring_idle(ring, seqno)) { ring->hangcheck.action = HANGCHECK_IDLE; if (waitqueue_active(&ring->irq_queue)) { diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 497cba5deb1e..849a2590e010 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -727,7 +727,7 @@ DECLARE_EVENT_CLASS(i915_context, TP_fast_assign( __entry->ctx = ctx; __entry->vm = ctx->ppgtt ? &ctx->ppgtt->base : NULL; - __entry->dev = ctx->file_priv->dev_priv->dev->primary->index; + __entry->dev = ctx->i915->dev->primary->index; ), TP_printk("dev=%u, ctx=%p, ctx_vm=%p", diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 198fc3c3291b..3dcd59e694db 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1075,15 +1075,34 @@ parse_device_mapping(struct drm_i915_private *dev_priv, const union child_device_config *p_child; union child_device_config *child_dev_ptr; int i, child_device_num, count; - u16 block_size; + u8 expected_size; + u16 block_size; p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); if (!p_defs) { DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n"); return; } - if (p_defs->child_dev_size < sizeof(*p_child)) { - DRM_ERROR("General definiton block child device size is too small.\n"); + if (bdb->version < 195) { + expected_size = 33; + } else if (bdb->version == 195) { + expected_size = 37; + } else if (bdb->version <= 197) { + expected_size = 38; + } else { + expected_size = 38; + DRM_DEBUG_DRIVER("Expected child_device_config size for BDB version %u not known; assuming %u\n", + expected_size, bdb->version); + } + + if (expected_size > sizeof(*p_child)) { + DRM_ERROR("child_device_config cannot fit in p_child\n"); + return; + } + + if (p_defs->child_dev_size != expected_size) { + DRM_ERROR("Size mismatch; child_device_config size=%u (expected %u); bdb->version: %u\n", + p_defs->child_dev_size, expected_size, bdb->version); return; } /* get the block size of general definitions */ @@ -1130,7 +1149,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv, child_dev_ptr = dev_priv->vbt.child_dev + count; count++; - memcpy(child_dev_ptr, p_child, sizeof(*p_child)); + memcpy(child_dev_ptr, p_child, p_defs->child_dev_size); } return; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1b61f9810387..30e0f54ba19d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4854,6 +4854,9 @@ static void intel_crtc_disable_planes(struct drm_crtc *crtc) struct intel_plane *intel_plane; int pipe = intel_crtc->pipe; + if (!intel_crtc->active) + return; + intel_crtc_wait_for_pending_flips(crtc); intel_pre_disable_primary(crtc); @@ -6312,9 +6315,6 @@ static void intel_crtc_disable(struct drm_crtc *crtc) struct drm_connector *connector; struct drm_i915_private *dev_priv = dev->dev_private; - /* crtc should still be enabled when we disable it. */ - WARN_ON(!crtc->state->enable); - intel_crtc_disable_planes(crtc); dev_priv->display.crtc_disable(crtc); dev_priv->display.off(crtc); @@ -7887,7 +7887,7 @@ static void chv_crtc_clock_get(struct intel_crtc *crtc, int pipe = pipe_config->cpu_transcoder; enum dpio_channel port = vlv_pipe_to_channel(pipe); intel_clock_t clock; - u32 cmn_dw13, pll_dw0, pll_dw1, pll_dw2; + u32 cmn_dw13, pll_dw0, pll_dw1, pll_dw2, pll_dw3; int refclk = 100000; mutex_lock(&dev_priv->sb_lock); @@ -7895,10 +7895,13 @@ static void chv_crtc_clock_get(struct intel_crtc *crtc, pll_dw0 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW0(port)); pll_dw1 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW1(port)); pll_dw2 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW2(port)); + pll_dw3 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW3(port)); mutex_unlock(&dev_priv->sb_lock); clock.m1 = (pll_dw1 & 0x7) == DPIO_CHV_M1_DIV_BY_2 ? 2 : 0; - clock.m2 = ((pll_dw0 & 0xff) << 22) | (pll_dw2 & 0x3fffff); + clock.m2 = (pll_dw0 & 0xff) << 22; + if (pll_dw3 & DPIO_CHV_FRAC_DIV_EN) + clock.m2 |= pll_dw2 & 0x3fffff; clock.n = (pll_dw1 >> DPIO_CHV_N_DIV_SHIFT) & 0xf; clock.p1 = (cmn_dw13 >> DPIO_CHV_P1_DIV_SHIFT) & 0x7; clock.p2 = (cmn_dw13 >> DPIO_CHV_P2_DIV_SHIFT) & 0x1f; @@ -12585,7 +12588,8 @@ static int __intel_set_mode(struct drm_crtc *modeset_crtc, continue; if (!crtc_state->enable) { - intel_crtc_disable(crtc); + if (crtc->state->enable) + intel_crtc_disable(crtc); } else if (crtc->state->enable) { intel_crtc_disable_planes(crtc); dev_priv->display.crtc_disable(crtc); @@ -13270,7 +13274,7 @@ intel_check_primary_plane(struct drm_plane *plane, if (ret) return ret; - if (intel_crtc->active) { + if (crtc_state ? crtc_state->base.active : intel_crtc->active) { struct intel_plane_state *old_state = to_intel_plane_state(plane->state); diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 6e4cc5334f47..600afdbef8c9 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -357,6 +357,16 @@ intel_dp_mst_mode_valid(struct drm_connector *connector, return MODE_OK; } +static struct drm_encoder *intel_mst_atomic_best_encoder(struct drm_connector *connector, + struct drm_connector_state *state) +{ + struct intel_connector *intel_connector = to_intel_connector(connector); + struct intel_dp *intel_dp = intel_connector->mst_port; + struct intel_crtc *crtc = to_intel_crtc(state->crtc); + + return &intel_dp->mst_encoders[crtc->pipe]->base.base; +} + static struct drm_encoder *intel_mst_best_encoder(struct drm_connector *connector) { struct intel_connector *intel_connector = to_intel_connector(connector); @@ -367,6 +377,7 @@ static struct drm_encoder *intel_mst_best_encoder(struct drm_connector *connecto static const struct drm_connector_helper_funcs intel_dp_mst_connector_helper_funcs = { .get_modes = intel_dp_mst_get_modes, .mode_valid = intel_dp_mst_mode_valid, + .atomic_best_encoder = intel_mst_atomic_best_encoder, .best_encoder = intel_mst_best_encoder, }; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index e539314ae87e..4be66f60504d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -275,6 +275,13 @@ struct intel_engine_cs { * Do we have some not yet emitted requests outstanding? */ struct drm_i915_gem_request *outstanding_lazy_request; + /** + * Seqno of request most recently submitted to request_list. + * Used exclusively by hang checker to avoid grabbing lock while + * inspecting request list. + */ + u32 last_submitted_seqno; + bool gpu_caches_dirty; wait_queue_head_t irq_queue; diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index a6d8a3ee7750..260389acfb77 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1274,10 +1274,12 @@ int i915_reg_read_ioctl(struct drm_device *dev, struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_reg_read *reg = data; struct register_whitelist const *entry = whitelist; + unsigned size; + u64 offset; int i, ret = 0; for (i = 0; i < ARRAY_SIZE(whitelist); i++, entry++) { - if (entry->offset == reg->offset && + if (entry->offset == (reg->offset & -entry->size) && (1 << INTEL_INFO(dev)->gen & entry->gen_bitmask)) break; } @@ -1285,23 +1287,33 @@ int i915_reg_read_ioctl(struct drm_device *dev, if (i == ARRAY_SIZE(whitelist)) return -EINVAL; + /* We use the low bits to encode extra flags as the register should + * be naturally aligned (and those that are not so aligned merely + * limit the available flags for that register). + */ + offset = entry->offset; + size = entry->size; + size |= reg->offset ^ offset; + intel_runtime_pm_get(dev_priv); - switch (entry->size) { + switch (size) { + case 8 | 1: + reg->val = I915_READ64_2x32(offset, offset+4); + break; case 8: - reg->val = I915_READ64(reg->offset); + reg->val = I915_READ64(offset); break; case 4: - reg->val = I915_READ(reg->offset); + reg->val = I915_READ(offset); break; case 2: - reg->val = I915_READ16(reg->offset); + reg->val = I915_READ16(offset); break; case 1: - reg->val = I915_READ8(reg->offset); + reg->val = I915_READ8(offset); break; default: - MISSING_CASE(entry->size); ret = -EINVAL; goto out; } diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c index 214eceefc981..e671ad369416 100644 --- a/drivers/gpu/drm/imx/imx-tve.c +++ b/drivers/gpu/drm/imx/imx-tve.c @@ -301,7 +301,7 @@ static void imx_tve_encoder_prepare(struct drm_encoder *encoder) switch (tve->mode) { case TVE_MODE_VGA: - imx_drm_set_bus_format_pins(encoder, MEDIA_BUS_FMT_YUV8_1X24, + imx_drm_set_bus_format_pins(encoder, MEDIA_BUS_FMT_GBR888_1X24, tve->hsync_pin, tve->vsync_pin); break; case TVE_MODE_TVOUT: diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index 74a9ce40ddc4..b4deb9cf9d71 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -21,6 +21,7 @@ #include <drm/drm_panel.h> #include <linux/videodev2.h> #include <video/of_display_timing.h> +#include <linux/of_graph.h> #include "imx-drm.h" @@ -208,7 +209,7 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data) { struct drm_device *drm = data; struct device_node *np = dev->of_node; - struct device_node *panel_node; + struct device_node *port; const u8 *edidp; struct imx_parallel_display *imxpd; int ret; @@ -234,11 +235,19 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data) imxpd->bus_format = MEDIA_BUS_FMT_RGB666_1X24_CPADHI; } - panel_node = of_parse_phandle(np, "fsl,panel", 0); - if (panel_node) { - imxpd->panel = of_drm_find_panel(panel_node); - if (!imxpd->panel) - return -EPROBE_DEFER; + /* port@1 is the output port */ + port = of_graph_get_port_by_id(np, 1); + if (port) { + struct device_node *endpoint, *remote; + + endpoint = of_get_child_by_name(port, "endpoint"); + if (endpoint) { + remote = of_graph_get_remote_port_parent(endpoint); + if (remote) + imxpd->panel = of_drm_find_panel(remote); + if (!imxpd->panel) + return -EPROBE_DEFER; + } } imxpd->dev = dev; diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c index 0d1dbb737933..247a424445f7 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c @@ -220,13 +220,15 @@ static int mdp4_plane_mode_set(struct drm_plane *plane, uint32_t op_mode = 0; uint32_t phasex_step = MDP4_VG_PHASE_STEP_DEFAULT; uint32_t phasey_step = MDP4_VG_PHASE_STEP_DEFAULT; - enum mdp4_frame_format frame_type = mdp4_get_frame_format(fb); + enum mdp4_frame_format frame_type; if (!(crtc && fb)) { DBG("%s: disabled!", mdp4_plane->name); return 0; } + frame_type = mdp4_get_frame_format(fb); + /* src values are in Q16 fixed point, convert to integer: */ src_x = src_x >> 16; src_y = src_y >> 16; diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c index 206f758f7d64..e253db5de5aa 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c @@ -76,7 +76,20 @@ static void mdp5_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *st static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *state) { + int i; struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); + int nplanes = mdp5_kms->dev->mode_config.num_total_plane; + + for (i = 0; i < nplanes; i++) { + struct drm_plane *plane = state->planes[i]; + struct drm_plane_state *plane_state = state->plane_states[i]; + + if (!plane) + continue; + + mdp5_plane_complete_commit(plane, plane_state); + } + mdp5_disable(mdp5_kms); } diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h index e0eb24587c84..e79ac09b7216 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h @@ -227,6 +227,8 @@ void mdp5_plane_install_properties(struct drm_plane *plane, struct drm_mode_object *obj); uint32_t mdp5_plane_get_flush(struct drm_plane *plane); void mdp5_plane_complete_flip(struct drm_plane *plane); +void mdp5_plane_complete_commit(struct drm_plane *plane, + struct drm_plane_state *state); enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane); struct drm_plane *mdp5_plane_init(struct drm_device *dev, enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset); diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index 57b8f56ae9d0..22275568ab8b 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c @@ -31,8 +31,6 @@ struct mdp5_plane { uint32_t nformats; uint32_t formats[32]; - - bool enabled; }; #define to_mdp5_plane(x) container_of(x, struct mdp5_plane, base) @@ -56,22 +54,6 @@ static bool plane_enabled(struct drm_plane_state *state) return state->fb && state->crtc; } -static int mdp5_plane_disable(struct drm_plane *plane) -{ - struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); - struct mdp5_kms *mdp5_kms = get_kms(plane); - enum mdp5_pipe pipe = mdp5_plane->pipe; - - DBG("%s: disable", mdp5_plane->name); - - if (mdp5_kms) { - /* Release the memory we requested earlier from the SMP: */ - mdp5_smp_release(mdp5_kms->smp, pipe); - } - - return 0; -} - static void mdp5_plane_destroy(struct drm_plane *plane) { struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); @@ -224,7 +206,6 @@ static void mdp5_plane_atomic_update(struct drm_plane *plane, if (!plane_enabled(state)) { to_mdp5_plane_state(state)->pending = true; - mdp5_plane_disable(plane); } else if (to_mdp5_plane_state(state)->mode_changed) { int ret; to_mdp5_plane_state(state)->pending = true; @@ -602,6 +583,20 @@ uint32_t mdp5_plane_get_flush(struct drm_plane *plane) return mdp5_plane->flush_mask; } +/* called after vsync in thread context */ +void mdp5_plane_complete_commit(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct mdp5_kms *mdp5_kms = get_kms(plane); + struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); + enum mdp5_pipe pipe = mdp5_plane->pipe; + + if (!plane_enabled(plane->state)) { + DBG("%s: free SMP", mdp5_plane->name); + mdp5_smp_release(mdp5_kms->smp, pipe); + } +} + /* initialize plane */ struct drm_plane *mdp5_plane_init(struct drm_device *dev, enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c index 16702aecf0df..64a27d86f2f5 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c @@ -34,22 +34,44 @@ * and CANNOT be re-allocated (eg: MMB0 and MMB1 both tied to RGB0). * * For each block that can be dynamically allocated, it can be either - * free, or pending/in-use by a client. The updates happen in three steps: + * free: + * The block is free. + * + * pending: + * The block is allocated to some client and not free. + * + * configured: + * The block is allocated to some client, and assigned to that + * client in MDP5_MDP_SMP_ALLOC registers. + * + * inuse: + * The block is being actively used by a client. + * + * The updates happen in the following steps: * * 1) mdp5_smp_request(): * When plane scanout is setup, calculate required number of - * blocks needed per client, and request. Blocks not inuse or - * pending by any other client are added to client's pending - * set. + * blocks needed per client, and request. Blocks neither inuse nor + * configured nor pending by any other client are added to client's + * pending set. + * For shrinking, blocks in pending but not in configured can be freed + * directly, but those already in configured will be freed later by + * mdp5_smp_commit. * * 2) mdp5_smp_configure(): * As hw is programmed, before FLUSH, MDP5_MDP_SMP_ALLOC registers * are configured for the union(pending, inuse) + * Current pending is copied to configured. + * It is assumed that mdp5_smp_request and mdp5_smp_configure not run + * concurrently for the same pipe. * * 3) mdp5_smp_commit(): - * After next vblank, copy pending -> inuse. Optionally update + * After next vblank, copy configured -> inuse. Optionally update * MDP5_SMP_ALLOC registers if there are newly unused blocks * + * 4) mdp5_smp_release(): + * Must be called after the pipe is disabled and no longer uses any SMB + * * On the next vblank after changes have been committed to hw, the * client's pending blocks become it's in-use blocks (and no-longer * in-use blocks become available to other clients). @@ -77,6 +99,9 @@ struct mdp5_smp { struct mdp5_client_smp_state client_state[MAX_CLIENTS]; }; +static void update_smp_state(struct mdp5_smp *smp, + u32 cid, mdp5_smp_state_t *assigned); + static inline struct mdp5_kms *get_kms(struct mdp5_smp *smp) { @@ -149,7 +174,12 @@ static int smp_request_block(struct mdp5_smp *smp, for (i = cur_nblks; i > nblks; i--) { int blk = find_first_bit(ps->pending, cnt); clear_bit(blk, ps->pending); - /* don't clear in global smp_state until _commit() */ + + /* clear in global smp_state if not in configured + * otherwise until _commit() + */ + if (!test_bit(blk, ps->configured)) + clear_bit(blk, smp->state); } } @@ -223,10 +253,33 @@ int mdp5_smp_request(struct mdp5_smp *smp, enum mdp5_pipe pipe, u32 fmt, u32 wid /* Release SMP blocks for all clients of the pipe */ void mdp5_smp_release(struct mdp5_smp *smp, enum mdp5_pipe pipe) { - int i, nblks; + int i; + unsigned long flags; + int cnt = smp->blk_cnt; + + for (i = 0; i < pipe2nclients(pipe); i++) { + mdp5_smp_state_t assigned; + u32 cid = pipe2client(pipe, i); + struct mdp5_client_smp_state *ps = &smp->client_state[cid]; + + spin_lock_irqsave(&smp->state_lock, flags); + + /* clear hw assignment */ + bitmap_or(assigned, ps->inuse, ps->configured, cnt); + update_smp_state(smp, CID_UNUSED, &assigned); + + /* free to global pool */ + bitmap_andnot(smp->state, smp->state, ps->pending, cnt); + bitmap_andnot(smp->state, smp->state, assigned, cnt); + + /* clear client's infor */ + bitmap_zero(ps->pending, cnt); + bitmap_zero(ps->configured, cnt); + bitmap_zero(ps->inuse, cnt); + + spin_unlock_irqrestore(&smp->state_lock, flags); + } - for (i = 0, nblks = 0; i < pipe2nclients(pipe); i++) - smp_request_block(smp, pipe2client(pipe, i), 0); set_fifo_thresholds(smp, pipe, 0); } @@ -274,12 +327,20 @@ void mdp5_smp_configure(struct mdp5_smp *smp, enum mdp5_pipe pipe) u32 cid = pipe2client(pipe, i); struct mdp5_client_smp_state *ps = &smp->client_state[cid]; - bitmap_or(assigned, ps->inuse, ps->pending, cnt); + /* + * if vblank has not happened since last smp_configure + * skip the configure for now + */ + if (!bitmap_equal(ps->inuse, ps->configured, cnt)) + continue; + + bitmap_copy(ps->configured, ps->pending, cnt); + bitmap_or(assigned, ps->inuse, ps->configured, cnt); update_smp_state(smp, cid, &assigned); } } -/* step #3: after vblank, copy pending -> inuse: */ +/* step #3: after vblank, copy configured -> inuse: */ void mdp5_smp_commit(struct mdp5_smp *smp, enum mdp5_pipe pipe) { int cnt = smp->blk_cnt; @@ -295,7 +356,7 @@ void mdp5_smp_commit(struct mdp5_smp *smp, enum mdp5_pipe pipe) * using, which can be released and made available to other * clients: */ - if (bitmap_andnot(released, ps->inuse, ps->pending, cnt)) { + if (bitmap_andnot(released, ps->inuse, ps->configured, cnt)) { unsigned long flags; spin_lock_irqsave(&smp->state_lock, flags); @@ -306,7 +367,7 @@ void mdp5_smp_commit(struct mdp5_smp *smp, enum mdp5_pipe pipe) update_smp_state(smp, CID_UNUSED, &released); } - bitmap_copy(ps->inuse, ps->pending, cnt); + bitmap_copy(ps->inuse, ps->configured, cnt); } } diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h index e47179f63585..5b6c2363f592 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h @@ -23,6 +23,7 @@ struct mdp5_client_smp_state { mdp5_smp_state_t inuse; + mdp5_smp_state_t configured; mdp5_smp_state_t pending; }; diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index 1b22d8bfe142..1ceb4f22dd89 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -283,12 +283,8 @@ int msm_atomic_commit(struct drm_device *dev, timeout = ktime_add_ms(ktime_get(), 1000); - ret = msm_wait_fence_interruptable(dev, c->fence, &timeout); - if (ret) { - WARN_ON(ret); // TODO unswap state back? or?? - commit_destroy(c); - return ret; - } + /* uninterruptible wait */ + msm_wait_fence(dev, c->fence, &timeout, false); complete_commit(c); diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index b7ef56ed8d1c..d3467b115e04 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -637,8 +637,8 @@ static void msm_debugfs_cleanup(struct drm_minor *minor) * Fences: */ -int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence, - ktime_t *timeout) +int msm_wait_fence(struct drm_device *dev, uint32_t fence, + ktime_t *timeout , bool interruptible) { struct msm_drm_private *priv = dev->dev_private; int ret; @@ -667,7 +667,12 @@ int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence, remaining_jiffies = timespec_to_jiffies(&ts); } - ret = wait_event_interruptible_timeout(priv->fence_event, + if (interruptible) + ret = wait_event_interruptible_timeout(priv->fence_event, + fence_completed(dev, fence), + remaining_jiffies); + else + ret = wait_event_timeout(priv->fence_event, fence_completed(dev, fence), remaining_jiffies); @@ -853,7 +858,7 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, return -EINVAL; } - return msm_wait_fence_interruptable(dev, args->fence, &timeout); + return msm_wait_fence(dev, args->fence, &timeout, true); } static const struct drm_ioctl_desc msm_ioctls[] = { diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index e7c5ea125d45..4ff0ec9c994b 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -164,8 +164,8 @@ int msm_atomic_commit(struct drm_device *dev, int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu); -int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence, - ktime_t *timeout); +int msm_wait_fence(struct drm_device *dev, uint32_t fence, + ktime_t *timeout, bool interruptible); int msm_queue_fence_cb(struct drm_device *dev, struct msm_fence_cb *cb, uint32_t fence); void msm_update_fence(struct drm_device *dev, uint32_t fence); diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index f211b80e3a1e..c76cc853b08a 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -460,7 +460,7 @@ int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout) if (op & MSM_PREP_NOSYNC) timeout = NULL; - ret = msm_wait_fence_interruptable(dev, fence, timeout); + ret = msm_wait_fence(dev, fence, timeout, true); } /* TODO cache maintenance */ diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c b/drivers/gpu/drm/msm/msm_gem_prime.c index dd7a7ab603e2..831461bc98a5 100644 --- a/drivers/gpu/drm/msm/msm_gem_prime.c +++ b/drivers/gpu/drm/msm/msm_gem_prime.c @@ -23,8 +23,12 @@ struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj) { struct msm_gem_object *msm_obj = to_msm_bo(obj); - BUG_ON(!msm_obj->sgt); /* should have already pinned! */ - return msm_obj->sgt; + int npages = obj->size >> PAGE_SHIFT; + + if (WARN_ON(!msm_obj->pages)) /* should have already pinned! */ + return NULL; + + return drm_prime_pages_to_sg(msm_obj->pages, npages); } void *msm_gem_prime_vmap(struct drm_gem_object *obj) diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 649024d4daf1..477cbb12809b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -128,6 +128,7 @@ nouveau_cli_destroy(struct nouveau_cli *cli) nvkm_vm_ref(NULL, &nvxx_client(&cli->base)->vm, NULL); nvif_client_fini(&cli->base); usif_client_fini(cli); + kfree(cli); } static void @@ -865,8 +866,10 @@ nouveau_drm_preclose(struct drm_device *dev, struct drm_file *fpriv) pm_runtime_get_sync(dev->dev); + mutex_lock(&cli->mutex); if (cli->abi16) nouveau_abi16_fini(cli->abi16); + mutex_unlock(&cli->mutex); mutex_lock(&drm->client.mutex); list_del(&cli->head); diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.c b/drivers/gpu/drm/nouveau/nouveau_platform.c index 775277f1edb0..dcfbbfaf1739 100644 --- a/drivers/gpu/drm/nouveau/nouveau_platform.c +++ b/drivers/gpu/drm/nouveau/nouveau_platform.c @@ -92,6 +92,8 @@ static int nouveau_platform_power_down(struct nouveau_platform_gpu *gpu) return 0; } +#if IS_ENABLED(CONFIG_IOMMU_API) + static void nouveau_platform_probe_iommu(struct device *dev, struct nouveau_platform_gpu *gpu) { @@ -158,6 +160,20 @@ static void nouveau_platform_remove_iommu(struct device *dev, } } +#else + +static void nouveau_platform_probe_iommu(struct device *dev, + struct nouveau_platform_gpu *gpu) +{ +} + +static void nouveau_platform_remove_iommu(struct device *dev, + struct nouveau_platform_gpu *gpu) +{ +} + +#endif + static int nouveau_platform_probe(struct platform_device *pdev) { struct nouveau_platform_gpu *gpu; diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 18f449715788..7464aef34674 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -175,15 +175,24 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man, node->page_shift = 12; switch (drm->device.info.family) { + case NV_DEVICE_INFO_V0_TNT: + case NV_DEVICE_INFO_V0_CELSIUS: + case NV_DEVICE_INFO_V0_KELVIN: + case NV_DEVICE_INFO_V0_RANKINE: + case NV_DEVICE_INFO_V0_CURIE: + break; case NV_DEVICE_INFO_V0_TESLA: if (drm->device.info.chipset != 0x50) node->memtype = (nvbo->tile_flags & 0x7f00) >> 8; break; case NV_DEVICE_INFO_V0_FERMI: case NV_DEVICE_INFO_V0_KEPLER: + case NV_DEVICE_INFO_V0_MAXWELL: node->memtype = (nvbo->tile_flags & 0xff00) >> 8; break; default: + NV_WARN(drm, "%s: unhandled family type %x\n", __func__, + drm->device.info.family); break; } diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c index 4ef602c5469d..495c57644ced 100644 --- a/drivers/gpu/drm/nouveau/nv04_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c @@ -203,7 +203,7 @@ nv04_fbcon_accel_init(struct fb_info *info) if (ret) return ret; - if (RING_SPACE(chan, 49)) { + if (RING_SPACE(chan, 49 + (device->info.chipset >= 0x11 ? 4 : 0))) { nouveau_fbcon_gpu_lockup(info); return 0; } diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 7da7958556a3..981342d142ff 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -979,7 +979,7 @@ nv50_crtc_cursor_show_hide(struct nouveau_crtc *nv_crtc, bool show, bool update) { struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev); - if (show && nv_crtc->cursor.nvbo) + if (show && nv_crtc->cursor.nvbo && nv_crtc->base.enabled) nv50_crtc_cursor_show(nv_crtc); else nv50_crtc_cursor_hide(nv_crtc); diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c index 394c89abcc97..901130b06072 100644 --- a/drivers/gpu/drm/nouveau/nv50_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c @@ -188,7 +188,7 @@ nv50_fbcon_accel_init(struct fb_info *info) if (ret) return ret; - ret = RING_SPACE(chan, 59); + ret = RING_SPACE(chan, 58); if (ret) { nouveau_fbcon_gpu_lockup(info); return ret; @@ -252,6 +252,7 @@ nv50_fbcon_accel_init(struct fb_info *info) OUT_RING(chan, info->var.yres_virtual); OUT_RING(chan, upper_32_bits(fb->vma.offset)); OUT_RING(chan, lower_32_bits(fb->vma.offset)); + FIRE_RING(chan); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvc0_fbcon.c b/drivers/gpu/drm/nouveau/nvc0_fbcon.c index 61246677e8dc..fcd2e5f27bb9 100644 --- a/drivers/gpu/drm/nouveau/nvc0_fbcon.c +++ b/drivers/gpu/drm/nouveau/nvc0_fbcon.c @@ -188,7 +188,7 @@ nvc0_fbcon_accel_init(struct fb_info *info) return -EINVAL; } - ret = RING_SPACE(chan, 60); + ret = RING_SPACE(chan, 58); if (ret) { WARN_ON(1); nouveau_fbcon_gpu_lockup(info); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c index 9ef6728c528d..7f2f05f78cc8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c @@ -809,7 +809,7 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl, case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break; default: nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl); - return 0x0000; + return NULL; } } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index e10f9644140f..52c22b026005 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -166,14 +166,30 @@ gk104_fifo_context_attach(struct nvkm_object *parent, } static int +gk104_fifo_chan_kick(struct gk104_fifo_chan *chan) +{ + struct nvkm_object *obj = (void *)chan; + struct gk104_fifo_priv *priv = (void *)obj->engine; + + nv_wr32(priv, 0x002634, chan->base.chid); + if (!nv_wait(priv, 0x002634, 0x100000, 0x000000)) { + nv_error(priv, "channel %d [%s] kick timeout\n", + chan->base.chid, nvkm_client_name(chan)); + return -EBUSY; + } + + return 0; +} + +static int gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend, struct nvkm_object *object) { struct nvkm_bar *bar = nvkm_bar(parent); - struct gk104_fifo_priv *priv = (void *)parent->engine; struct gk104_fifo_base *base = (void *)parent->parent; struct gk104_fifo_chan *chan = (void *)parent; u32 addr; + int ret; switch (nv_engidx(object->engine)) { case NVDEV_ENGINE_SW : return 0; @@ -188,13 +204,9 @@ gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend, return -EINVAL; } - nv_wr32(priv, 0x002634, chan->base.chid); - if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) { - nv_error(priv, "channel %d [%s] kick timeout\n", - chan->base.chid, nvkm_client_name(chan)); - if (suspend) - return -EBUSY; - } + ret = gk104_fifo_chan_kick(chan); + if (ret && suspend) + return ret; if (addr) { nv_wo32(base, addr + 0x00, 0x00000000); @@ -319,6 +331,7 @@ gk104_fifo_chan_fini(struct nvkm_object *object, bool suspend) gk104_fifo_runlist_update(priv, chan->engine); } + gk104_fifo_chan_kick(chan); nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000); return nvkm_fifo_channel_fini(&chan->base, suspend); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 5606c25e5d02..ca11ddb6ed46 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -663,6 +663,37 @@ gf100_gr_zbc_init(struct gf100_gr_priv *priv) gf100_gr_zbc_clear_depth(priv, index); } +/** + * Wait until GR goes idle. GR is considered idle if it is disabled by the + * MC (0x200) register, or GR is not busy and a context switch is not in + * progress. + */ +int +gf100_gr_wait_idle(struct gf100_gr_priv *priv) +{ + unsigned long end_jiffies = jiffies + msecs_to_jiffies(2000); + bool gr_enabled, ctxsw_active, gr_busy; + + do { + /* + * required to make sure FIFO_ENGINE_STATUS (0x2640) is + * up-to-date + */ + nv_rd32(priv, 0x400700); + + gr_enabled = nv_rd32(priv, 0x200) & 0x1000; + ctxsw_active = nv_rd32(priv, 0x2640) & 0x8000; + gr_busy = nv_rd32(priv, 0x40060c) & 0x1; + + if (!gr_enabled || (!gr_busy && !ctxsw_active)) + return 0; + } while (time_before(jiffies, end_jiffies)); + + nv_error(priv, "wait for idle timeout (en: %d, ctxsw: %d, busy: %d)\n", + gr_enabled, ctxsw_active, gr_busy); + return -EAGAIN; +} + void gf100_gr_mmio(struct gf100_gr_priv *priv, const struct gf100_gr_pack *p) { @@ -699,7 +730,13 @@ gf100_gr_icmd(struct gf100_gr_priv *priv, const struct gf100_gr_pack *p) while (addr < next) { nv_wr32(priv, 0x400200, addr); - nv_wait(priv, 0x400700, 0x00000002, 0x00000000); + /** + * Wait for GR to go idle after submitting a + * GO_IDLE bundle + */ + if ((addr & 0xffff) == 0xe100) + gf100_gr_wait_idle(priv); + nv_wait(priv, 0x400700, 0x00000004, 0x00000000); addr += init->pitch; } } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index 8af1a89eda84..c9533fdac4fc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -181,6 +181,7 @@ struct gf100_gr_oclass { int ppc_nr; }; +int gf100_gr_wait_idle(struct gf100_gr_priv *); void gf100_gr_mmio(struct gf100_gr_priv *, const struct gf100_gr_pack *); void gf100_gr_icmd(struct gf100_gr_priv *, const struct gf100_gr_pack *); void gf100_gr_mthd(struct gf100_gr_priv *, const struct gf100_gr_pack *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c index 2006c445938d..4cf36a3aa814 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c @@ -332,9 +332,12 @@ static void nvkm_perfctx_dtor(struct nvkm_object *object) { struct nvkm_pm *ppm = (void *)object->engine; + struct nvkm_perfctx *ctx = (void *)object; + mutex_lock(&nv_subdev(ppm)->mutex); - nvkm_engctx_destroy(&ppm->context->base); - ppm->context = NULL; + nvkm_engctx_destroy(&ctx->base); + if (ppm->context == ctx) + ppm->context = NULL; mutex_unlock(&nv_subdev(ppm)->mutex); } @@ -355,12 +358,11 @@ nvkm_perfctx_ctor(struct nvkm_object *parent, struct nvkm_object *engine, mutex_lock(&nv_subdev(ppm)->mutex); if (ppm->context == NULL) ppm->context = ctx; - mutex_unlock(&nv_subdev(ppm)->mutex); - if (ctx != ppm->context) - return -EBUSY; + ret = -EBUSY; + mutex_unlock(&nv_subdev(ppm)->mutex); - return 0; + return ret; } struct nvkm_oclass diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c index f67cdae1e90a..f4611e3f0971 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c @@ -1285,6 +1285,44 @@ init_zm_reg_sequence(struct nvbios_init *init) } /** + * INIT_PLL_INDIRECT - opcode 0x59 + * + */ +static void +init_pll_indirect(struct nvbios_init *init) +{ + struct nvkm_bios *bios = init->bios; + u32 reg = nv_ro32(bios, init->offset + 1); + u16 addr = nv_ro16(bios, init->offset + 5); + u32 freq = (u32)nv_ro16(bios, addr) * 1000; + + trace("PLL_INDIRECT\tR[0x%06x] =PLL= VBIOS[%04x] = %dkHz\n", + reg, addr, freq); + init->offset += 7; + + init_prog_pll(init, reg, freq); +} + +/** + * INIT_ZM_REG_INDIRECT - opcode 0x5a + * + */ +static void +init_zm_reg_indirect(struct nvbios_init *init) +{ + struct nvkm_bios *bios = init->bios; + u32 reg = nv_ro32(bios, init->offset + 1); + u16 addr = nv_ro16(bios, init->offset + 5); + u32 data = nv_ro32(bios, addr); + + trace("ZM_REG_INDIRECT\tR[0x%06x] = VBIOS[0x%04x] = 0x%08x\n", + reg, addr, data); + init->offset += 7; + + init_wr32(init, addr, data); +} + +/** * INIT_SUB_DIRECT - opcode 0x5b * */ @@ -2145,6 +2183,8 @@ static struct nvbios_init_opcode { [0x56] = { init_condition_time }, [0x57] = { init_ltime }, [0x58] = { init_zm_reg_sequence }, + [0x59] = { init_pll_indirect }, + [0x5a] = { init_zm_reg_indirect }, [0x5b] = { init_sub_direct }, [0x5c] = { init_jump }, [0x5e] = { init_i2c_if }, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c index 822d32a28d6e..065e9f5c8db9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c @@ -180,7 +180,8 @@ gt215_clk_info(struct nvkm_clk *clock, int clk, u32 khz, struct gt215_clk_info *info) { struct gt215_clk_priv *priv = (void *)clock; - u32 oclk, sclk, sdiv, diff; + u32 oclk, sclk, sdiv; + s32 diff; info->clk = 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c index c0fdb89e74ac..24dcdfb58a8d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c @@ -38,6 +38,14 @@ gk20a_ibus_init_priv_ring(struct gk20a_ibus_priv *priv) nv_wr32(priv, 0x12004c, 0x4); nv_wr32(priv, 0x122204, 0x2); nv_rd32(priv, 0x122204); + + /* + * Bug: increase clock timeout to avoid operation failure at high + * gpcclk rate. + */ + nv_wr32(priv, 0x122354, 0x800); + nv_wr32(priv, 0x128328, 0x800); + nv_wr32(priv, 0x124320, 0x800); } static void diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c index 80614f1b2074..282143f49d72 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c @@ -50,7 +50,12 @@ nv04_instobj_dtor(struct nvkm_object *object) { struct nv04_instmem_priv *priv = (void *)nvkm_instmem(object); struct nv04_instobj_priv *node = (void *)object; + struct nvkm_subdev *subdev = (void *)priv; + + mutex_lock(&subdev->mutex); nvkm_mm_free(&priv->heap, &node->mem); + mutex_unlock(&subdev->mutex); + nvkm_instobj_destroy(&node->base); } @@ -62,6 +67,7 @@ nv04_instobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine, struct nv04_instmem_priv *priv = (void *)nvkm_instmem(parent); struct nv04_instobj_priv *node; struct nvkm_instobj_args *args = data; + struct nvkm_subdev *subdev = (void *)priv; int ret; if (!args->align) @@ -72,8 +78,10 @@ nv04_instobj_ctor(struct nvkm_object *parent, struct nvkm_object *engine, if (ret) return ret; + mutex_lock(&subdev->mutex); ret = nvkm_mm_head(&priv->heap, 0, 1, args->size, args->size, args->align, &node->mem); + mutex_unlock(&subdev->mutex); if (ret) return ret; diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c index f2daad8c3d96..7841970de48d 100644 --- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c +++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c @@ -285,7 +285,7 @@ static int dmm_txn_commit(struct dmm_txn *txn, bool wait) if (wait) { if (!wait_for_completion_timeout(&engine->compl, - msecs_to_jiffies(1))) { + msecs_to_jiffies(100))) { dev_err(dmm->dev, "timed out waiting for done\n"); ret = -ETIMEDOUT; } diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index ae2df41f216f..12081e61d45a 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -177,7 +177,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos); struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p); int omap_framebuffer_pin(struct drm_framebuffer *fb); -int omap_framebuffer_unpin(struct drm_framebuffer *fb); +void omap_framebuffer_unpin(struct drm_framebuffer *fb); void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, struct omap_drm_window *win, struct omap_overlay_info *info); struct drm_connector *omap_framebuffer_get_next_connector( @@ -211,7 +211,7 @@ void omap_gem_dma_sync(struct drm_gem_object *obj, enum dma_data_direction dir); int omap_gem_get_paddr(struct drm_gem_object *obj, dma_addr_t *paddr, bool remap); -int omap_gem_put_paddr(struct drm_gem_object *obj); +void omap_gem_put_paddr(struct drm_gem_object *obj); int omap_gem_get_pages(struct drm_gem_object *obj, struct page ***pages, bool remap); int omap_gem_put_pages(struct drm_gem_object *obj); @@ -236,7 +236,7 @@ static inline int align_pitch(int pitch, int width, int bpp) /* PVR needs alignment to 8 pixels.. right now that is the most * restrictive stride requirement.. */ - return ALIGN(pitch, 8 * bytespp); + return roundup(pitch, 8 * bytespp); } /* map crtc to vblank mask */ diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index 0b967e76df1a..51b1219af87f 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c @@ -287,10 +287,10 @@ fail: } /* unpin, no longer being scanned out: */ -int omap_framebuffer_unpin(struct drm_framebuffer *fb) +void omap_framebuffer_unpin(struct drm_framebuffer *fb) { struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb); - int ret, i, n = drm_format_num_planes(fb->pixel_format); + int i, n = drm_format_num_planes(fb->pixel_format); mutex_lock(&omap_fb->lock); @@ -298,24 +298,16 @@ int omap_framebuffer_unpin(struct drm_framebuffer *fb) if (omap_fb->pin_count > 0) { mutex_unlock(&omap_fb->lock); - return 0; + return; } for (i = 0; i < n; i++) { struct plane *plane = &omap_fb->planes[i]; - ret = omap_gem_put_paddr(plane->bo); - if (ret) - goto fail; + omap_gem_put_paddr(plane->bo); plane->paddr = 0; } mutex_unlock(&omap_fb->lock); - - return 0; - -fail: - mutex_unlock(&omap_fb->lock); - return ret; } struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p) diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index 23b5a84389e3..720d16bce7e8 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c @@ -135,7 +135,7 @@ static int omap_fbdev_create(struct drm_fb_helper *helper, fbdev->ywrap_enabled = priv->has_dmm && ywrap_enabled; if (fbdev->ywrap_enabled) { /* need to align pitch to page size if using DMM scrolling */ - mode_cmd.pitches[0] = ALIGN(mode_cmd.pitches[0], PAGE_SIZE); + mode_cmd.pitches[0] = PAGE_ALIGN(mode_cmd.pitches[0]); } /* allocate backing bo */ diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 2ab77801cf5f..7ed08fdc4c42 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -808,10 +808,10 @@ fail: /* Release physical address, when DMA is no longer being performed.. this * could potentially unpin and unmap buffers from TILER */ -int omap_gem_put_paddr(struct drm_gem_object *obj) +void omap_gem_put_paddr(struct drm_gem_object *obj) { struct omap_gem_object *omap_obj = to_omap_bo(obj); - int ret = 0; + int ret; mutex_lock(&obj->dev->struct_mutex); if (omap_obj->paddr_cnt > 0) { @@ -821,7 +821,6 @@ int omap_gem_put_paddr(struct drm_gem_object *obj) if (ret) { dev_err(obj->dev->dev, "could not unpin pages: %d\n", ret); - goto fail; } ret = tiler_release(omap_obj->block); if (ret) { @@ -832,9 +831,8 @@ int omap_gem_put_paddr(struct drm_gem_object *obj) omap_obj->block = NULL; } } -fail: + mutex_unlock(&obj->dev->struct_mutex); - return ret; } /* Get rotated scanout address (only valid if already pinned), at the @@ -1378,11 +1376,7 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, omap_obj = kzalloc(sizeof(*omap_obj), GFP_KERNEL); if (!omap_obj) - goto fail; - - spin_lock(&priv->list_lock); - list_add(&omap_obj->mm_list, &priv->obj_list); - spin_unlock(&priv->list_lock); + return NULL; obj = &omap_obj->base; @@ -1392,11 +1386,19 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, */ omap_obj->vaddr = dma_alloc_writecombine(dev->dev, size, &omap_obj->paddr, GFP_KERNEL); - if (omap_obj->vaddr) - flags |= OMAP_BO_DMA; + if (!omap_obj->vaddr) { + kfree(omap_obj); + + return NULL; + } + flags |= OMAP_BO_DMA; } + spin_lock(&priv->list_lock); + list_add(&omap_obj->mm_list, &priv->obj_list); + spin_unlock(&priv->list_lock); + omap_obj->flags = flags; if (flags & OMAP_BO_TILED) { diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index cfa8276c4deb..098904696a5c 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -17,6 +17,7 @@ * this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_plane_helper.h> @@ -153,9 +154,34 @@ static void omap_plane_atomic_disable(struct drm_plane *plane, dispc_ovl_enable(omap_plane->id, false); } +static int omap_plane_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct drm_crtc_state *crtc_state; + + if (!state->crtc) + return 0; + + crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + + if (state->crtc_x < 0 || state->crtc_y < 0) + return -EINVAL; + + if (state->crtc_x + state->crtc_w > crtc_state->adjusted_mode.hdisplay) + return -EINVAL; + + if (state->crtc_y + state->crtc_h > crtc_state->adjusted_mode.vdisplay) + return -EINVAL; + + return 0; +} + static const struct drm_plane_helper_funcs omap_plane_helper_funcs = { .prepare_fb = omap_plane_prepare_fb, .cleanup_fb = omap_plane_cleanup_fb, + .atomic_check = omap_plane_atomic_check, .atomic_update = omap_plane_atomic_update, .atomic_disable = omap_plane_atomic_disable, }; diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index dd39f434b4a7..c3872598b85a 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -2299,8 +2299,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, encoder_mode = atombios_get_encoder_mode(encoder); if (connector && (radeon_audio != 0) && ((encoder_mode == ATOM_ENCODER_MODE_HDMI) || - (ENCODER_MODE_IS_DP(encoder_mode) && - drm_detect_monitor_audio(radeon_connector_edid(connector))))) + ENCODER_MODE_IS_DP(encoder_mode))) radeon_audio_mode_set(encoder, adjusted_mode); } diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 8730562323a8..4a09947be244 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -5818,7 +5818,7 @@ int ci_dpm_init(struct radeon_device *rdev) tmp |= DPM_ENABLED; break; default: - DRM_ERROR("Invalid PCC GPIO: %u!\n", gpio.shift); + DRM_DEBUG("Invalid PCC GPIO: %u!\n", gpio.shift); break; } WREG32_SMC(CNB_PWRMGT_CNTL, tmp); diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 4ecf5caa8c6d..248953d2fdb7 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -7964,23 +7964,27 @@ restart_ih: case 1: /* D1 vblank/vline */ switch (src_data) { case 0: /* D1 vblank */ - if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[0]) { - drm_handle_vblank(rdev->ddev, 0); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[0])) - radeon_crtc_handle_vblank(rdev, 0); - rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D1 vblank\n"); + if (!(rdev->irq.stat_regs.cik.disp_int & LB_D1_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[0]) { + drm_handle_vblank(rdev->ddev, 0); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[0])) + radeon_crtc_handle_vblank(rdev, 0); + rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D1 vblank\n"); + break; case 1: /* D1 vline */ - if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VLINE_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VLINE_INTERRUPT; - DRM_DEBUG("IH: D1 vline\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int & LB_D1_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VLINE_INTERRUPT; + DRM_DEBUG("IH: D1 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -7990,23 +7994,27 @@ restart_ih: case 2: /* D2 vblank/vline */ switch (src_data) { case 0: /* D2 vblank */ - if (rdev->irq.stat_regs.cik.disp_int_cont & LB_D2_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[1]) { - drm_handle_vblank(rdev->ddev, 1); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[1])) - radeon_crtc_handle_vblank(rdev, 1); - rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D2 vblank\n"); + if (!(rdev->irq.stat_regs.cik.disp_int_cont & LB_D2_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[1]) { + drm_handle_vblank(rdev->ddev, 1); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[1])) + radeon_crtc_handle_vblank(rdev, 1); + rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D2 vblank\n"); + break; case 1: /* D2 vline */ - if (rdev->irq.stat_regs.cik.disp_int_cont & LB_D2_VLINE_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; - DRM_DEBUG("IH: D2 vline\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont & LB_D2_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; + DRM_DEBUG("IH: D2 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -8016,23 +8024,27 @@ restart_ih: case 3: /* D3 vblank/vline */ switch (src_data) { case 0: /* D3 vblank */ - if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[2]) { - drm_handle_vblank(rdev->ddev, 2); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[2])) - radeon_crtc_handle_vblank(rdev, 2); - rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D3 vblank\n"); + if (!(rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[2]) { + drm_handle_vblank(rdev->ddev, 2); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[2])) + radeon_crtc_handle_vblank(rdev, 2); + rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D3 vblank\n"); + break; case 1: /* D3 vline */ - if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; - DRM_DEBUG("IH: D3 vline\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; + DRM_DEBUG("IH: D3 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -8042,23 +8054,27 @@ restart_ih: case 4: /* D4 vblank/vline */ switch (src_data) { case 0: /* D4 vblank */ - if (rdev->irq.stat_regs.cik.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[3]) { - drm_handle_vblank(rdev->ddev, 3); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[3])) - radeon_crtc_handle_vblank(rdev, 3); - rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D4 vblank\n"); + if (!(rdev->irq.stat_regs.cik.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[3]) { + drm_handle_vblank(rdev->ddev, 3); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[3])) + radeon_crtc_handle_vblank(rdev, 3); + rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D4 vblank\n"); + break; case 1: /* D4 vline */ - if (rdev->irq.stat_regs.cik.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; - DRM_DEBUG("IH: D4 vline\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont3 & LB_D4_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; + DRM_DEBUG("IH: D4 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -8068,23 +8084,27 @@ restart_ih: case 5: /* D5 vblank/vline */ switch (src_data) { case 0: /* D5 vblank */ - if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[4]) { - drm_handle_vblank(rdev->ddev, 4); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[4])) - radeon_crtc_handle_vblank(rdev, 4); - rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D5 vblank\n"); + if (!(rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[4]) { + drm_handle_vblank(rdev->ddev, 4); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[4])) + radeon_crtc_handle_vblank(rdev, 4); + rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D5 vblank\n"); + break; case 1: /* D5 vline */ - if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; - DRM_DEBUG("IH: D5 vline\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; + DRM_DEBUG("IH: D5 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -8094,23 +8114,27 @@ restart_ih: case 6: /* D6 vblank/vline */ switch (src_data) { case 0: /* D6 vblank */ - if (rdev->irq.stat_regs.cik.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[5]) { - drm_handle_vblank(rdev->ddev, 5); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[5])) - radeon_crtc_handle_vblank(rdev, 5); - rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D6 vblank\n"); + if (!(rdev->irq.stat_regs.cik.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[5]) { + drm_handle_vblank(rdev->ddev, 5); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[5])) + radeon_crtc_handle_vblank(rdev, 5); + rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D6 vblank\n"); + break; case 1: /* D6 vline */ - if (rdev->irq.stat_regs.cik.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; - DRM_DEBUG("IH: D6 vline\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont5 & LB_D6_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; + DRM_DEBUG("IH: D6 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -8130,88 +8154,112 @@ restart_ih: case 42: /* HPD hotplug */ switch (src_data) { case 0: - if (rdev->irq.stat_regs.cik.disp_int & DC_HPD1_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int &= ~DC_HPD1_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD1\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int & DC_HPD1_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int &= ~DC_HPD1_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD1\n"); + break; case 1: - if (rdev->irq.stat_regs.cik.disp_int_cont & DC_HPD2_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont &= ~DC_HPD2_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD2\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont & DC_HPD2_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont &= ~DC_HPD2_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD2\n"); + break; case 2: - if (rdev->irq.stat_regs.cik.disp_int_cont2 & DC_HPD3_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD3\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont2 & DC_HPD3_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD3\n"); + break; case 3: - if (rdev->irq.stat_regs.cik.disp_int_cont3 & DC_HPD4_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD4\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont3 & DC_HPD4_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD4\n"); + break; case 4: - if (rdev->irq.stat_regs.cik.disp_int_cont4 & DC_HPD5_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD5\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont4 & DC_HPD5_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD5\n"); + break; case 5: - if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD6\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD6\n"); + break; case 6: - if (rdev->irq.stat_regs.cik.disp_int & DC_HPD1_RX_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int &= ~DC_HPD1_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 1\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int & DC_HPD1_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int &= ~DC_HPD1_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 1\n"); + break; case 7: - if (rdev->irq.stat_regs.cik.disp_int_cont & DC_HPD2_RX_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 2\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont & DC_HPD2_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 2\n"); + break; case 8: - if (rdev->irq.stat_regs.cik.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 3\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont2 & DC_HPD3_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 3\n"); + break; case 9: - if (rdev->irq.stat_regs.cik.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 4\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont3 & DC_HPD4_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 4\n"); + break; case 10: - if (rdev->irq.stat_regs.cik.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 5\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont4 & DC_HPD5_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 5\n"); + break; case 11: - if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) { - rdev->irq.stat_regs.cik.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 6\n"); - } + if (!(rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.cik.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 6\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index 68fd9fc677e3..44480c1b9738 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c @@ -93,30 +93,26 @@ void dce6_afmt_select_pin(struct drm_encoder *encoder) struct radeon_device *rdev = encoder->dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - u32 offset; - if (!dig || !dig->afmt || !dig->afmt->pin) + if (!dig || !dig->afmt || !dig->pin) return; - offset = dig->afmt->offset; - - WREG32(AFMT_AUDIO_SRC_CONTROL + offset, - AFMT_AUDIO_SRC_SELECT(dig->afmt->pin->id)); + WREG32(AFMT_AUDIO_SRC_CONTROL + dig->afmt->offset, + AFMT_AUDIO_SRC_SELECT(dig->pin->id)); } void dce6_afmt_write_latency_fields(struct drm_encoder *encoder, - struct drm_connector *connector, struct drm_display_mode *mode) + struct drm_connector *connector, + struct drm_display_mode *mode) { struct radeon_device *rdev = encoder->dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - u32 tmp = 0, offset; + u32 tmp = 0; - if (!dig || !dig->afmt || !dig->afmt->pin) + if (!dig || !dig->afmt || !dig->pin) return; - offset = dig->afmt->pin->offset; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) { if (connector->latency_present[1]) tmp = VIDEO_LIPSYNC(connector->video_latency[1]) | @@ -130,24 +126,24 @@ void dce6_afmt_write_latency_fields(struct drm_encoder *encoder, else tmp = VIDEO_LIPSYNC(0) | AUDIO_LIPSYNC(0); } - WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, tmp); + WREG32_ENDPOINT(dig->pin->offset, + AZ_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, tmp); } void dce6_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder, - u8 *sadb, int sad_count) + u8 *sadb, int sad_count) { struct radeon_device *rdev = encoder->dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - u32 offset, tmp; + u32 tmp; - if (!dig || !dig->afmt || !dig->afmt->pin) + if (!dig || !dig->afmt || !dig->pin) return; - offset = dig->afmt->pin->offset; - /* program the speaker allocation */ - tmp = RREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER); + tmp = RREG32_ENDPOINT(dig->pin->offset, + AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER); tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK); /* set HDMI mode */ tmp |= HDMI_CONNECTION; @@ -155,24 +151,24 @@ void dce6_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder, tmp |= SPEAKER_ALLOCATION(sadb[0]); else tmp |= SPEAKER_ALLOCATION(5); /* stereo */ - WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp); + WREG32_ENDPOINT(dig->pin->offset, + AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp); } void dce6_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder, - u8 *sadb, int sad_count) + u8 *sadb, int sad_count) { struct radeon_device *rdev = encoder->dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - u32 offset, tmp; + u32 tmp; - if (!dig || !dig->afmt || !dig->afmt->pin) + if (!dig || !dig->afmt || !dig->pin) return; - offset = dig->afmt->pin->offset; - /* program the speaker allocation */ - tmp = RREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER); + tmp = RREG32_ENDPOINT(dig->pin->offset, + AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER); tmp &= ~(HDMI_CONNECTION | SPEAKER_ALLOCATION_MASK); /* set DP mode */ tmp |= DP_CONNECTION; @@ -180,13 +176,13 @@ void dce6_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder, tmp |= SPEAKER_ALLOCATION(sadb[0]); else tmp |= SPEAKER_ALLOCATION(5); /* stereo */ - WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp); + WREG32_ENDPOINT(dig->pin->offset, + AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp); } void dce6_afmt_write_sad_regs(struct drm_encoder *encoder, - struct cea_sad *sads, int sad_count) + struct cea_sad *sads, int sad_count) { - u32 offset; int i; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; @@ -206,11 +202,9 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder, { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO }, }; - if (!dig || !dig->afmt || !dig->afmt->pin) + if (!dig || !dig->afmt || !dig->pin) return; - offset = dig->afmt->pin->offset; - for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) { u32 value = 0; u8 stereo_freqs = 0; @@ -237,7 +231,7 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder, value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs); - WREG32_ENDPOINT(offset, eld_reg_to_type[i][0], value); + WREG32_ENDPOINT(dig->pin->offset, eld_reg_to_type[i][0], value); } } @@ -253,7 +247,7 @@ void dce6_audio_enable(struct radeon_device *rdev, } void dce6_hdmi_audio_set_dto(struct radeon_device *rdev, - struct radeon_crtc *crtc, unsigned int clock) + struct radeon_crtc *crtc, unsigned int clock) { /* Two dtos; generally use dto0 for HDMI */ u32 value = 0; @@ -272,7 +266,7 @@ void dce6_hdmi_audio_set_dto(struct radeon_device *rdev, } void dce6_dp_audio_set_dto(struct radeon_device *rdev, - struct radeon_crtc *crtc, unsigned int clock) + struct radeon_crtc *crtc, unsigned int clock) { /* Two dtos; generally use dto1 for DP */ u32 value = 0; diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 3a6d483a2c36..0acde1949c18 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -4924,7 +4924,7 @@ restart_ih: return IRQ_NONE; rptr = rdev->ih.rptr; - DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); + DRM_DEBUG("evergreen_irq_process start: rptr %d, wptr %d\n", rptr, wptr); /* Order reading of wptr vs. reading of IH ring data */ rmb(); @@ -4942,23 +4942,27 @@ restart_ih: case 1: /* D1 vblank/vline */ switch (src_data) { case 0: /* D1 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[0]) { - drm_handle_vblank(rdev->ddev, 0); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[0])) - radeon_crtc_handle_vblank(rdev, 0); - rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D1 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: D1 vblank - IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[0]) { + drm_handle_vblank(rdev->ddev, 0); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[0])) + radeon_crtc_handle_vblank(rdev, 0); + rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D1 vblank\n"); + break; case 1: /* D1 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VLINE_INTERRUPT; - DRM_DEBUG("IH: D1 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT)) + DRM_DEBUG("IH: D1 vline - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VLINE_INTERRUPT; + DRM_DEBUG("IH: D1 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -4968,23 +4972,27 @@ restart_ih: case 2: /* D2 vblank/vline */ switch (src_data) { case 0: /* D2 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[1]) { - drm_handle_vblank(rdev->ddev, 1); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[1])) - radeon_crtc_handle_vblank(rdev, 1); - rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D2 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: D2 vblank - IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[1]) { + drm_handle_vblank(rdev->ddev, 1); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[1])) + radeon_crtc_handle_vblank(rdev, 1); + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D2 vblank\n"); + break; case 1: /* D2 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; - DRM_DEBUG("IH: D2 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT)) + DRM_DEBUG("IH: D2 vline - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; + DRM_DEBUG("IH: D2 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -4994,23 +5002,27 @@ restart_ih: case 3: /* D3 vblank/vline */ switch (src_data) { case 0: /* D3 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[2]) { - drm_handle_vblank(rdev->ddev, 2); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[2])) - radeon_crtc_handle_vblank(rdev, 2); - rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D3 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: D3 vblank - IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[2]) { + drm_handle_vblank(rdev->ddev, 2); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[2])) + radeon_crtc_handle_vblank(rdev, 2); + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D3 vblank\n"); + break; case 1: /* D3 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; - DRM_DEBUG("IH: D3 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)) + DRM_DEBUG("IH: D3 vline - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; + DRM_DEBUG("IH: D3 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -5020,23 +5032,27 @@ restart_ih: case 4: /* D4 vblank/vline */ switch (src_data) { case 0: /* D4 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[3]) { - drm_handle_vblank(rdev->ddev, 3); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[3])) - radeon_crtc_handle_vblank(rdev, 3); - rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D4 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: D4 vblank - IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[3]) { + drm_handle_vblank(rdev->ddev, 3); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[3])) + radeon_crtc_handle_vblank(rdev, 3); + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D4 vblank\n"); + break; case 1: /* D4 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; - DRM_DEBUG("IH: D4 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT)) + DRM_DEBUG("IH: D4 vline - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; + DRM_DEBUG("IH: D4 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -5046,23 +5062,27 @@ restart_ih: case 5: /* D5 vblank/vline */ switch (src_data) { case 0: /* D5 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[4]) { - drm_handle_vblank(rdev->ddev, 4); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[4])) - radeon_crtc_handle_vblank(rdev, 4); - rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D5 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: D5 vblank - IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[4]) { + drm_handle_vblank(rdev->ddev, 4); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[4])) + radeon_crtc_handle_vblank(rdev, 4); + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D5 vblank\n"); + break; case 1: /* D5 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; - DRM_DEBUG("IH: D5 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)) + DRM_DEBUG("IH: D5 vline - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; + DRM_DEBUG("IH: D5 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -5072,23 +5092,27 @@ restart_ih: case 6: /* D6 vblank/vline */ switch (src_data) { case 0: /* D6 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[5]) { - drm_handle_vblank(rdev->ddev, 5); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[5])) - radeon_crtc_handle_vblank(rdev, 5); - rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D6 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: D6 vblank - IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[5]) { + drm_handle_vblank(rdev->ddev, 5); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[5])) + radeon_crtc_handle_vblank(rdev, 5); + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D6 vblank\n"); + break; case 1: /* D6 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; - DRM_DEBUG("IH: D6 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT)) + DRM_DEBUG("IH: D6 vline - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; + DRM_DEBUG("IH: D6 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -5108,88 +5132,100 @@ restart_ih: case 42: /* HPD hotplug */ switch (src_data) { case 0: - if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD1\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD1\n"); break; case 1: - if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD2\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD2\n"); break; case 2: - if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD3\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD3\n"); break; case 3: - if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD4\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD4\n"); break; case 4: - if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD5\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD5\n"); break; case 5: - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD6\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD6\n"); break; case 6: - if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 1\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 1\n"); break; case 7: - if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 2\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 2\n"); break; case 8: - if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 3\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 3\n"); break; case 9: - if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 4\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 4\n"); break; case 10: - if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 5\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 5\n"); break; case 11: - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 6\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 6\n"); break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -5199,46 +5235,52 @@ restart_ih: case 44: /* hdmi */ switch (src_data) { case 0: - if (rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG) { - rdev->irq.stat_regs.evergreen.afmt_status1 &= ~AFMT_AZ_FORMAT_WTRIG; - queue_hdmi = true; - DRM_DEBUG("IH: HDMI0\n"); - } + if (!(rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.afmt_status1 &= ~AFMT_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI0\n"); break; case 1: - if (rdev->irq.stat_regs.evergreen.afmt_status2 & AFMT_AZ_FORMAT_WTRIG) { - rdev->irq.stat_regs.evergreen.afmt_status2 &= ~AFMT_AZ_FORMAT_WTRIG; - queue_hdmi = true; - DRM_DEBUG("IH: HDMI1\n"); - } + if (!(rdev->irq.stat_regs.evergreen.afmt_status2 & AFMT_AZ_FORMAT_WTRIG)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.afmt_status2 &= ~AFMT_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI1\n"); break; case 2: - if (rdev->irq.stat_regs.evergreen.afmt_status3 & AFMT_AZ_FORMAT_WTRIG) { - rdev->irq.stat_regs.evergreen.afmt_status3 &= ~AFMT_AZ_FORMAT_WTRIG; - queue_hdmi = true; - DRM_DEBUG("IH: HDMI2\n"); - } + if (!(rdev->irq.stat_regs.evergreen.afmt_status3 & AFMT_AZ_FORMAT_WTRIG)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.afmt_status3 &= ~AFMT_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI2\n"); break; case 3: - if (rdev->irq.stat_regs.evergreen.afmt_status4 & AFMT_AZ_FORMAT_WTRIG) { - rdev->irq.stat_regs.evergreen.afmt_status4 &= ~AFMT_AZ_FORMAT_WTRIG; - queue_hdmi = true; - DRM_DEBUG("IH: HDMI3\n"); - } + if (!(rdev->irq.stat_regs.evergreen.afmt_status4 & AFMT_AZ_FORMAT_WTRIG)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.afmt_status4 &= ~AFMT_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI3\n"); break; case 4: - if (rdev->irq.stat_regs.evergreen.afmt_status5 & AFMT_AZ_FORMAT_WTRIG) { - rdev->irq.stat_regs.evergreen.afmt_status5 &= ~AFMT_AZ_FORMAT_WTRIG; - queue_hdmi = true; - DRM_DEBUG("IH: HDMI4\n"); - } + if (!(rdev->irq.stat_regs.evergreen.afmt_status5 & AFMT_AZ_FORMAT_WTRIG)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.afmt_status5 &= ~AFMT_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI4\n"); break; case 5: - if (rdev->irq.stat_regs.evergreen.afmt_status6 & AFMT_AZ_FORMAT_WTRIG) { - rdev->irq.stat_regs.evergreen.afmt_status6 &= ~AFMT_AZ_FORMAT_WTRIG; - queue_hdmi = true; - DRM_DEBUG("IH: HDMI5\n"); - } + if (!(rdev->irq.stat_regs.evergreen.afmt_status6 & AFMT_AZ_FORMAT_WTRIG)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.afmt_status6 &= ~AFMT_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI5\n"); break; default: DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 8e5aeeb058a5..158872eb78e4 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -2162,18 +2162,20 @@ static int cayman_startup(struct radeon_device *rdev) DRM_ERROR("radeon: failed initializing UVD (%d).\n", r); } - ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX]; - if (ring->ring_size) - r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0); + if (rdev->family == CHIP_ARUBA) { + ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX]; + if (ring->ring_size) + r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0); - ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX]; - if (ring->ring_size) - r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0); + ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX]; + if (ring->ring_size) + r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0); - if (!r) - r = vce_v1_0_init(rdev); - else if (r != -ENOENT) - DRM_ERROR("radeon: failed initializing VCE (%d).\n", r); + if (!r) + r = vce_v1_0_init(rdev); + if (r) + DRM_ERROR("radeon: failed initializing VCE (%d).\n", r); + } r = radeon_ib_pool_init(rdev); if (r) { @@ -2396,7 +2398,8 @@ void cayman_fini(struct radeon_device *rdev) radeon_irq_kms_fini(rdev); uvd_v1_0_fini(rdev); radeon_uvd_fini(rdev); - radeon_vce_fini(rdev); + if (rdev->family == CHIP_ARUBA) + radeon_vce_fini(rdev); cayman_pcie_gart_fini(rdev); r600_vram_scratch_fini(rdev); radeon_gem_fini(rdev); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 35dafd77a639..4ea5b10ff5f4 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -4086,23 +4086,27 @@ restart_ih: case 1: /* D1 vblank/vline */ switch (src_data) { case 0: /* D1 vblank */ - if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[0]) { - drm_handle_vblank(rdev->ddev, 0); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[0])) - radeon_crtc_handle_vblank(rdev, 0); - rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D1 vblank\n"); + if (!(rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: D1 vblank - IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[0]) { + drm_handle_vblank(rdev->ddev, 0); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[0])) + radeon_crtc_handle_vblank(rdev, 0); + rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D1 vblank\n"); + break; case 1: /* D1 vline */ - if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT) { - rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VLINE_INTERRUPT; - DRM_DEBUG("IH: D1 vline\n"); - } + if (!(rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT)) + DRM_DEBUG("IH: D1 vline - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VLINE_INTERRUPT; + DRM_DEBUG("IH: D1 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -4112,23 +4116,27 @@ restart_ih: case 5: /* D2 vblank/vline */ switch (src_data) { case 0: /* D2 vblank */ - if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[1]) { - drm_handle_vblank(rdev->ddev, 1); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[1])) - radeon_crtc_handle_vblank(rdev, 1); - rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D2 vblank\n"); + if (!(rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: D2 vblank - IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[1]) { + drm_handle_vblank(rdev->ddev, 1); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[1])) + radeon_crtc_handle_vblank(rdev, 1); + rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D2 vblank\n"); + break; case 1: /* D1 vline */ - if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT) { - rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VLINE_INTERRUPT; - DRM_DEBUG("IH: D2 vline\n"); - } + if (!(rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT)) + DRM_DEBUG("IH: D2 vline - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VLINE_INTERRUPT; + DRM_DEBUG("IH: D2 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -4148,46 +4156,53 @@ restart_ih: case 19: /* HPD/DAC hotplug */ switch (src_data) { case 0: - if (rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT) { - rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD1_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD1\n"); - } + if (!(rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT)) + DRM_DEBUG("IH: HPD1 - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD1_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD1\n"); break; case 1: - if (rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT) { - rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD2_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD2\n"); - } + if (!(rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT)) + DRM_DEBUG("IH: HPD2 - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD2_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD2\n"); break; case 4: - if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT) { - rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD3_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD3\n"); - } + if (!(rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT)) + DRM_DEBUG("IH: HPD3 - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD3_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD3\n"); break; case 5: - if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT) { - rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD4_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD4\n"); - } + if (!(rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT)) + DRM_DEBUG("IH: HPD4 - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD4_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD4\n"); break; case 10: - if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT) { - rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD5_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD5\n"); - } + if (!(rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT)) + DRM_DEBUG("IH: HPD5 - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD5_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD5\n"); break; case 12: - if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) { - rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD6_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD6\n"); - } + if (!(rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT)) + DRM_DEBUG("IH: HPD6 - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD6_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD6\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -4197,18 +4212,22 @@ restart_ih: case 21: /* hdmi */ switch (src_data) { case 4: - if (rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG) { - rdev->irq.stat_regs.r600.hdmi0_status &= ~HDMI0_AZ_FORMAT_WTRIG; - queue_hdmi = true; - DRM_DEBUG("IH: HDMI0\n"); - } + if (!(rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG)) + DRM_DEBUG("IH: HDMI0 - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.r600.hdmi0_status &= ~HDMI0_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI0\n"); + break; case 5: - if (rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG) { - rdev->irq.stat_regs.r600.hdmi1_status &= ~HDMI0_AZ_FORMAT_WTRIG; - queue_hdmi = true; - DRM_DEBUG("IH: HDMI1\n"); - } + if (!(rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG)) + DRM_DEBUG("IH: HDMI1 - IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.r600.hdmi1_status &= ~HDMI0_AZ_FORMAT_WTRIG; + queue_hdmi = true; + DRM_DEBUG("IH: HDMI1\n"); + break; default: DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c index 09e3f39925fa..98f9adaccc3d 100644 --- a/drivers/gpu/drm/radeon/r600_cp.c +++ b/drivers/gpu/drm/radeon/r600_cp.c @@ -2483,7 +2483,7 @@ int r600_cp_dispatch_texture(struct drm_device *dev, struct drm_buf *buf; u32 *buffer; const u8 __user *data; - int size, pass_size; + unsigned int size, pass_size; u64 src_offset, dst_offset; if (!radeon_check_offset(dev_priv, tex->offset)) { diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c index fa719c53449b..fbc8d88d6e5d 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.c +++ b/drivers/gpu/drm/radeon/radeon_audio.c @@ -245,6 +245,28 @@ static struct radeon_audio_funcs dce6_dp_funcs = { static void radeon_audio_enable(struct radeon_device *rdev, struct r600_audio_pin *pin, u8 enable_mask) { + struct drm_encoder *encoder; + struct radeon_encoder *radeon_encoder; + struct radeon_encoder_atom_dig *dig; + int pin_count = 0; + + if (!pin) + return; + + if (rdev->mode_info.mode_config_initialized) { + list_for_each_entry(encoder, &rdev->ddev->mode_config.encoder_list, head) { + if (radeon_encoder_is_digital(encoder)) { + radeon_encoder = to_radeon_encoder(encoder); + dig = radeon_encoder->enc_priv; + if (dig->pin == pin) + pin_count++; + } + } + + if ((pin_count > 1) && (enable_mask == 0)) + return; + } + if (rdev->audio.funcs->enable) rdev->audio.funcs->enable(rdev, pin, enable_mask); } @@ -336,24 +358,13 @@ void radeon_audio_endpoint_wreg(struct radeon_device *rdev, u32 offset, static void radeon_audio_write_sad_regs(struct drm_encoder *encoder) { - struct radeon_encoder *radeon_encoder; - struct drm_connector *connector; - struct radeon_connector *radeon_connector = NULL; + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct cea_sad *sads; int sad_count; - list_for_each_entry(connector, - &encoder->dev->mode_config.connector_list, head) { - if (connector->encoder == encoder) { - radeon_connector = to_radeon_connector(connector); - break; - } - } - - if (!radeon_connector) { - DRM_ERROR("Couldn't find encoder's connector\n"); + if (!connector) return; - } sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads); if (sad_count <= 0) { @@ -362,8 +373,6 @@ static void radeon_audio_write_sad_regs(struct drm_encoder *encoder) } BUG_ON(!sads); - radeon_encoder = to_radeon_encoder(encoder); - if (radeon_encoder->audio && radeon_encoder->audio->write_sad_regs) radeon_encoder->audio->write_sad_regs(encoder, sads, sad_count); @@ -372,27 +381,16 @@ static void radeon_audio_write_sad_regs(struct drm_encoder *encoder) static void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder) { + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - struct drm_connector *connector; - struct radeon_connector *radeon_connector = NULL; u8 *sadb = NULL; int sad_count; - list_for_each_entry(connector, - &encoder->dev->mode_config.connector_list, head) { - if (connector->encoder == encoder) { - radeon_connector = to_radeon_connector(connector); - break; - } - } - - if (!radeon_connector) { - DRM_ERROR("Couldn't find encoder's connector\n"); + if (!connector) return; - } - sad_count = drm_edid_to_speaker_allocation( - radeon_connector_edid(connector), &sadb); + sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector), + &sadb); if (sad_count < 0) { DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n", sad_count); @@ -406,26 +404,13 @@ static void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder) } static void radeon_audio_write_latency_fields(struct drm_encoder *encoder, - struct drm_display_mode *mode) + struct drm_display_mode *mode) { - struct radeon_encoder *radeon_encoder; - struct drm_connector *connector; - struct radeon_connector *radeon_connector = 0; - - list_for_each_entry(connector, - &encoder->dev->mode_config.connector_list, head) { - if (connector->encoder == encoder) { - radeon_connector = to_radeon_connector(connector); - break; - } - } + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - if (!radeon_connector) { - DRM_ERROR("Couldn't find encoder's connector\n"); + if (!connector) return; - } - - radeon_encoder = to_radeon_encoder(encoder); if (radeon_encoder->audio && radeon_encoder->audio->write_latency_fields) radeon_encoder->audio->write_latency_fields(encoder, connector, mode); @@ -451,29 +436,23 @@ static void radeon_audio_select_pin(struct drm_encoder *encoder) } void radeon_audio_detect(struct drm_connector *connector, + struct drm_encoder *encoder, enum drm_connector_status status) { - struct radeon_device *rdev; - struct radeon_encoder *radeon_encoder; + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig; - if (!connector || !connector->encoder) + if (!radeon_audio_chipset_supported(rdev)) return; - rdev = connector->encoder->dev->dev_private; - - if (!radeon_audio_chipset_supported(rdev)) + if (!radeon_encoder_is_digital(encoder)) return; - radeon_encoder = to_radeon_encoder(connector->encoder); dig = radeon_encoder->enc_priv; if (status == connector_status_connected) { - if (!drm_detect_monitor_audio(radeon_connector_edid(connector))) { - radeon_encoder->audio = NULL; - return; - } - if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -486,11 +465,17 @@ void radeon_audio_detect(struct drm_connector *connector, radeon_encoder->audio = rdev->audio.hdmi_funcs; } - dig->afmt->pin = radeon_audio_get_pin(connector->encoder); - radeon_audio_enable(rdev, dig->afmt->pin, 0xf); + if (drm_detect_monitor_audio(radeon_connector_edid(connector))) { + if (!dig->pin) + dig->pin = radeon_audio_get_pin(encoder); + radeon_audio_enable(rdev, dig->pin, 0xf); + } else { + radeon_audio_enable(rdev, dig->pin, 0); + dig->pin = NULL; + } } else { - radeon_audio_enable(rdev, dig->afmt->pin, 0); - dig->afmt->pin = NULL; + radeon_audio_enable(rdev, dig->pin, 0); + dig->pin = NULL; } } @@ -518,29 +503,18 @@ static void radeon_audio_set_dto(struct drm_encoder *encoder, unsigned int clock } static int radeon_audio_set_avi_packet(struct drm_encoder *encoder, - struct drm_display_mode *mode) + struct drm_display_mode *mode) { struct radeon_device *rdev = encoder->dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - struct drm_connector *connector; - struct radeon_connector *radeon_connector = NULL; + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; struct hdmi_avi_infoframe frame; int err; - list_for_each_entry(connector, - &encoder->dev->mode_config.connector_list, head) { - if (connector->encoder == encoder) { - radeon_connector = to_radeon_connector(connector); - break; - } - } - - if (!radeon_connector) { - DRM_ERROR("Couldn't find encoder's connector\n"); - return -ENOENT; - } + if (!connector) + return -EINVAL; err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); if (err < 0) { @@ -563,8 +537,8 @@ static int radeon_audio_set_avi_packet(struct drm_encoder *encoder, return err; } - if (dig && dig->afmt && - radeon_encoder->audio && radeon_encoder->audio->set_avi_packet) + if (dig && dig->afmt && radeon_encoder->audio && + radeon_encoder->audio->set_avi_packet) radeon_encoder->audio->set_avi_packet(rdev, dig->afmt->offset, buffer, sizeof(buffer)); @@ -722,30 +696,41 @@ static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder, { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); if (!dig || !dig->afmt) return; - radeon_audio_set_mute(encoder, true); + if (!connector) + return; - radeon_audio_write_speaker_allocation(encoder); - radeon_audio_write_sad_regs(encoder); - radeon_audio_write_latency_fields(encoder, mode); - radeon_audio_set_dto(encoder, mode->clock); - radeon_audio_set_vbi_packet(encoder); - radeon_hdmi_set_color_depth(encoder); - radeon_audio_update_acr(encoder, mode->clock); - radeon_audio_set_audio_packet(encoder); - radeon_audio_select_pin(encoder); + if (drm_detect_monitor_audio(radeon_connector_edid(connector))) { + radeon_audio_set_mute(encoder, true); - if (radeon_audio_set_avi_packet(encoder, mode) < 0) - return; + radeon_audio_write_speaker_allocation(encoder); + radeon_audio_write_sad_regs(encoder); + radeon_audio_write_latency_fields(encoder, mode); + radeon_audio_set_dto(encoder, mode->clock); + radeon_audio_set_vbi_packet(encoder); + radeon_hdmi_set_color_depth(encoder); + radeon_audio_update_acr(encoder, mode->clock); + radeon_audio_set_audio_packet(encoder); + radeon_audio_select_pin(encoder); + + if (radeon_audio_set_avi_packet(encoder, mode) < 0) + return; - radeon_audio_set_mute(encoder, false); + radeon_audio_set_mute(encoder, false); + } else { + radeon_hdmi_set_color_depth(encoder); + + if (radeon_audio_set_avi_packet(encoder, mode) < 0) + return; + } } static void radeon_audio_dp_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode) + struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; @@ -759,22 +744,27 @@ static void radeon_audio_dp_mode_set(struct drm_encoder *encoder, if (!dig || !dig->afmt) return; - radeon_audio_write_speaker_allocation(encoder); - radeon_audio_write_sad_regs(encoder); - radeon_audio_write_latency_fields(encoder, mode); - if (rdev->clock.dp_extclk || ASIC_IS_DCE5(rdev)) - radeon_audio_set_dto(encoder, rdev->clock.default_dispclk * 10); - else - radeon_audio_set_dto(encoder, dig_connector->dp_clock); - radeon_audio_set_audio_packet(encoder); - radeon_audio_select_pin(encoder); - - if (radeon_audio_set_avi_packet(encoder, mode) < 0) + if (!connector) return; + + if (drm_detect_monitor_audio(radeon_connector_edid(connector))) { + radeon_audio_write_speaker_allocation(encoder); + radeon_audio_write_sad_regs(encoder); + radeon_audio_write_latency_fields(encoder, mode); + if (rdev->clock.dp_extclk || ASIC_IS_DCE5(rdev)) + radeon_audio_set_dto(encoder, rdev->clock.default_dispclk * 10); + else + radeon_audio_set_dto(encoder, dig_connector->dp_clock); + radeon_audio_set_audio_packet(encoder); + radeon_audio_select_pin(encoder); + + if (radeon_audio_set_avi_packet(encoder, mode) < 0) + return; + } } void radeon_audio_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode) + struct drm_display_mode *mode) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); diff --git a/drivers/gpu/drm/radeon/radeon_audio.h b/drivers/gpu/drm/radeon/radeon_audio.h index 8438304f7139..059cc3012062 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.h +++ b/drivers/gpu/drm/radeon/radeon_audio.h @@ -68,7 +68,8 @@ struct radeon_audio_funcs int radeon_audio_init(struct radeon_device *rdev); void radeon_audio_detect(struct drm_connector *connector, - enum drm_connector_status status); + struct drm_encoder *encoder, + enum drm_connector_status status); u32 radeon_audio_endpoint_rreg(struct radeon_device *rdev, u32 offset, u32 reg); void radeon_audio_endpoint_wreg(struct radeon_device *rdev, diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 3e5f6b71f3ad..c097d3a82bda 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -1255,10 +1255,15 @@ struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder if ((RBIOS16(tmp) == lvds->native_mode.hdisplay) && (RBIOS16(tmp + 2) == lvds->native_mode.vdisplay)) { + u32 hss = (RBIOS16(tmp + 21) - RBIOS16(tmp + 19) - 1) * 8; + + if (hss > lvds->native_mode.hdisplay) + hss = (10 - 1) * 8; + lvds->native_mode.htotal = lvds->native_mode.hdisplay + (RBIOS16(tmp + 17) - RBIOS16(tmp + 19)) * 8; lvds->native_mode.hsync_start = lvds->native_mode.hdisplay + - (RBIOS16(tmp + 21) - RBIOS16(tmp + 19) - 1) * 8; + hss; lvds->native_mode.hsync_end = lvds->native_mode.hsync_start + (RBIOS8(tmp + 23) * 8); diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index cebb65e07e1d..94b21ae70ef7 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -1379,8 +1379,16 @@ out: /* updated in get modes as well since we need to know if it's analog or digital */ radeon_connector_update_scratch_regs(connector, ret); - if (radeon_audio != 0) - radeon_audio_detect(connector, ret); + if ((radeon_audio != 0) && radeon_connector->use_digital) { + const struct drm_connector_helper_funcs *connector_funcs = + connector->helper_private; + + encoder = connector_funcs->best_encoder(connector); + if (encoder && (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)) { + radeon_connector_get_edid(connector); + radeon_audio_detect(connector, encoder, ret); + } + } exit: pm_runtime_mark_last_busy(connector->dev->dev); @@ -1717,8 +1725,10 @@ radeon_dp_detect(struct drm_connector *connector, bool force) radeon_connector_update_scratch_regs(connector, ret); - if (radeon_audio != 0) - radeon_audio_detect(connector, ret); + if ((radeon_audio != 0) && encoder) { + radeon_connector_get_edid(connector); + radeon_audio_detect(connector, encoder, ret); + } out: pm_runtime_mark_last_busy(connector->dev->dev); diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 45e54060ee97..afaf346bd50e 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c @@ -91,15 +91,34 @@ static void radeon_show_cursor(struct drm_crtc *crtc) struct radeon_device *rdev = crtc->dev->dev_private; if (ASIC_IS_DCE4(rdev)) { + WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, + upper_32_bits(radeon_crtc->cursor_addr)); + WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + lower_32_bits(radeon_crtc->cursor_addr)); WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset); WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_EN | EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) | EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2)); } else if (ASIC_IS_AVIVO(rdev)) { + if (rdev->family >= CHIP_RV770) { + if (radeon_crtc->crtc_id) + WREG32(R700_D2CUR_SURFACE_ADDRESS_HIGH, + upper_32_bits(radeon_crtc->cursor_addr)); + else + WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH, + upper_32_bits(radeon_crtc->cursor_addr)); + } + + WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + lower_32_bits(radeon_crtc->cursor_addr)); WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset); WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN | (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); } else { + /* offset is from DISP(2)_BASE_ADDRESS */ + WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, + radeon_crtc->cursor_addr - radeon_crtc->legacy_display_base_addr); + switch (radeon_crtc->crtc_id) { case 0: WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL); @@ -205,8 +224,9 @@ static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y) | (x << 16) | y)); /* offset is from DISP(2)_BASE_ADDRESS */ - WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, (radeon_crtc->legacy_cursor_offset + - (yorigin * 256))); + WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, + radeon_crtc->cursor_addr - radeon_crtc->legacy_display_base_addr + + yorigin * 256); } radeon_crtc->cursor_x = x; @@ -227,53 +247,6 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, return ret; } -static int radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj) -{ - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - struct radeon_device *rdev = crtc->dev->dev_private; - struct radeon_bo *robj = gem_to_radeon_bo(obj); - uint64_t gpu_addr; - int ret; - - ret = radeon_bo_reserve(robj, false); - if (unlikely(ret != 0)) - goto fail; - /* Only 27 bit offset for legacy cursor */ - ret = radeon_bo_pin_restricted(robj, RADEON_GEM_DOMAIN_VRAM, - ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, - &gpu_addr); - radeon_bo_unreserve(robj); - if (ret) - goto fail; - - if (ASIC_IS_DCE4(rdev)) { - WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, - upper_32_bits(gpu_addr)); - WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, - gpu_addr & 0xffffffff); - } else if (ASIC_IS_AVIVO(rdev)) { - if (rdev->family >= CHIP_RV770) { - if (radeon_crtc->crtc_id) - WREG32(R700_D2CUR_SURFACE_ADDRESS_HIGH, upper_32_bits(gpu_addr)); - else - WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH, upper_32_bits(gpu_addr)); - } - WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, - gpu_addr & 0xffffffff); - } else { - radeon_crtc->legacy_cursor_offset = gpu_addr - radeon_crtc->legacy_display_base_addr; - /* offset is from DISP(2)_BASE_ADDRESS */ - WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, radeon_crtc->legacy_cursor_offset); - } - - return 0; - -fail: - drm_gem_object_unreference_unlocked(obj); - - return ret; -} - int radeon_crtc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv, uint32_t handle, @@ -283,7 +256,9 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc, int32_t hot_y) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct radeon_device *rdev = crtc->dev->dev_private; struct drm_gem_object *obj; + struct radeon_bo *robj; int ret; if (!handle) { @@ -305,6 +280,23 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc, return -ENOENT; } + robj = gem_to_radeon_bo(obj); + ret = radeon_bo_reserve(robj, false); + if (ret != 0) { + drm_gem_object_unreference_unlocked(obj); + return ret; + } + /* Only 27 bit offset for legacy cursor */ + ret = radeon_bo_pin_restricted(robj, RADEON_GEM_DOMAIN_VRAM, + ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, + &radeon_crtc->cursor_addr); + radeon_bo_unreserve(robj); + if (ret) { + DRM_ERROR("Failed to pin new cursor BO (%d)\n", ret); + drm_gem_object_unreference_unlocked(obj); + return ret; + } + radeon_crtc->cursor_width = width; radeon_crtc->cursor_height = height; @@ -323,13 +315,7 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc, radeon_crtc->cursor_hot_y = hot_y; } - ret = radeon_set_cursor(crtc, obj); - - if (ret) - DRM_ERROR("radeon_set_cursor returned %d, not changing cursor\n", - ret); - else - radeon_show_cursor(crtc); + radeon_show_cursor(crtc); radeon_lock_cursor(crtc, false); @@ -341,8 +327,7 @@ unpin: radeon_bo_unpin(robj); radeon_bo_unreserve(robj); } - if (radeon_crtc->cursor_bo != obj) - drm_gem_object_unreference_unlocked(radeon_crtc->cursor_bo); + drm_gem_object_unreference_unlocked(radeon_crtc->cursor_bo); } radeon_crtc->cursor_bo = obj; @@ -360,7 +345,6 @@ unpin: void radeon_cursor_reset(struct drm_crtc *crtc) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - int ret; if (radeon_crtc->cursor_bo) { radeon_lock_cursor(crtc, true); @@ -368,12 +352,7 @@ void radeon_cursor_reset(struct drm_crtc *crtc) radeon_cursor_move_locked(crtc, radeon_crtc->cursor_x, radeon_crtc->cursor_y); - ret = radeon_set_cursor(crtc, radeon_crtc->cursor_bo); - if (ret) - DRM_ERROR("radeon_set_cursor returned %d, not showing " - "cursor\n", ret); - else - radeon_show_cursor(crtc); + radeon_show_cursor(crtc); radeon_lock_cursor(crtc, false); } diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 2593b1168bd6..d8319dae8358 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1080,6 +1080,22 @@ static bool radeon_check_pot_argument(int arg) } /** + * Determine a sensible default GART size according to ASIC family. + * + * @family ASIC family name + */ +static int radeon_gart_size_auto(enum radeon_family family) +{ + /* default to a larger gart size on newer asics */ + if (family >= CHIP_TAHITI) + return 2048; + else if (family >= CHIP_RV770) + return 1024; + else + return 512; +} + +/** * radeon_check_arguments - validate module params * * @rdev: radeon_device pointer @@ -1097,27 +1113,17 @@ static void radeon_check_arguments(struct radeon_device *rdev) } if (radeon_gart_size == -1) { - /* default to a larger gart size on newer asics */ - if (rdev->family >= CHIP_RV770) - radeon_gart_size = 1024; - else - radeon_gart_size = 512; + radeon_gart_size = radeon_gart_size_auto(rdev->family); } /* gtt size must be power of two and greater or equal to 32M */ if (radeon_gart_size < 32) { dev_warn(rdev->dev, "gart size (%d) too small\n", radeon_gart_size); - if (rdev->family >= CHIP_RV770) - radeon_gart_size = 1024; - else - radeon_gart_size = 512; + radeon_gart_size = radeon_gart_size_auto(rdev->family); } else if (!radeon_check_pot_argument(radeon_gart_size)) { dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n", radeon_gart_size); - if (rdev->family >= CHIP_RV770) - radeon_gart_size = 1024; - else - radeon_gart_size = 512; + radeon_gart_size = radeon_gart_size_auto(rdev->family); } rdev->mc.gtt_size = (uint64_t)radeon_gart_size << 20; @@ -1572,11 +1578,21 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon) drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); } - /* unpin the front buffers */ + /* unpin the front buffers and cursors */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->primary->fb); struct radeon_bo *robj; + if (radeon_crtc->cursor_bo) { + struct radeon_bo *robj = gem_to_radeon_bo(radeon_crtc->cursor_bo); + r = radeon_bo_reserve(robj, false); + if (r == 0) { + radeon_bo_unpin(robj); + radeon_bo_unreserve(robj); + } + } + if (rfb == NULL || rfb->obj == NULL) { continue; } @@ -1639,6 +1655,7 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon) { struct drm_connector *connector; struct radeon_device *rdev = dev->dev_private; + struct drm_crtc *crtc; int r; if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) @@ -1678,6 +1695,27 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon) radeon_restore_bios_scratch_regs(rdev); + /* pin cursors */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + + if (radeon_crtc->cursor_bo) { + struct radeon_bo *robj = gem_to_radeon_bo(radeon_crtc->cursor_bo); + r = radeon_bo_reserve(robj, false); + if (r == 0) { + /* Only 27 bit offset for legacy cursor */ + r = radeon_bo_pin_restricted(robj, + RADEON_GEM_DOMAIN_VRAM, + ASIC_IS_AVIVO(rdev) ? + 0 : 1 << 27, + &radeon_crtc->cursor_addr); + if (r != 0) + DRM_ERROR("Failed to pin cursor BO (%d)\n", r); + radeon_bo_unreserve(robj); + } + } + } + /* init dig PHYs, disp eng pll */ if (rdev->is_atom_bios) { radeon_atom_encoder_init(rdev); diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 634793ea8418..aeb676708e60 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -257,6 +257,7 @@ static int radeonfb_create(struct drm_fb_helper *helper, } info->par = rfbdev; + info->skip_vt_switch = true; ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj); if (ret) { diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 5450fa95a47e..c4777c8d0312 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -260,8 +260,10 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, } } } - mb(); - radeon_gart_tlb_flush(rdev); + if (rdev->gart.ptr) { + mb(); + radeon_gart_tlb_flush(rdev); + } } /** @@ -306,8 +308,10 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, page_base += RADEON_GPU_PAGE_SIZE; } } - mb(); - radeon_gart_tlb_flush(rdev); + if (rdev->gart.ptr) { + mb(); + radeon_gart_tlb_flush(rdev); + } return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index ac3c1310b953..3dcc5733ff69 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -36,6 +36,7 @@ void radeon_gem_object_free(struct drm_gem_object *gobj) if (robj) { if (robj->gem_base.import_attach) drm_prime_gem_destroy(&robj->gem_base, robj->tbo.sg); + radeon_mn_unregister(robj); radeon_bo_unref(&robj); } } @@ -428,7 +429,6 @@ int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { - struct radeon_device *rdev = dev->dev_private; struct drm_radeon_gem_busy *args = data; struct drm_gem_object *gobj; struct radeon_bo *robj; @@ -440,10 +440,16 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, return -ENOENT; } robj = gem_to_radeon_bo(gobj); - r = radeon_bo_wait(robj, &cur_placement, true); + + r = reservation_object_test_signaled_rcu(robj->tbo.resv, true); + if (r == 0) + r = -EBUSY; + else + r = 0; + + cur_placement = ACCESS_ONCE(robj->tbo.mem.mem_type); args->domain = radeon_mem_type_to_domain(cur_placement); drm_gem_object_unreference_unlocked(gobj); - r = radeon_gem_handle_lockup(rdev, r); return r; } @@ -471,6 +477,7 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, r = ret; /* Flush HDP cache via MMIO if necessary */ + cur_placement = ACCESS_ONCE(robj->tbo.mem.mem_type); if (rdev->asic->mmio_hdp_flush && radeon_mem_type_to_domain(cur_placement) == RADEON_GEM_DOMAIN_VRAM) robj->rdev->asic->mmio_hdp_flush(rdev); diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 6de5459316b5..aecc3e3dec0c 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -237,7 +237,6 @@ struct radeon_afmt { int offset; bool last_buffer_filled_status; int id; - struct r600_audio_pin *pin; }; struct radeon_mode_info { @@ -343,7 +342,6 @@ struct radeon_crtc { int max_cursor_width; int max_cursor_height; uint32_t legacy_display_base_addr; - uint32_t legacy_cursor_offset; enum radeon_rmx_type rmx_type; u8 h_border; u8 v_border; @@ -440,6 +438,7 @@ struct radeon_encoder_atom_dig { uint8_t backlight_level; int panel_mode; struct radeon_afmt *afmt; + struct r600_audio_pin *pin; int active_mst_links; }; diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 318165d4855c..676362769b8d 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -75,7 +75,6 @@ static void radeon_ttm_bo_destroy(struct ttm_buffer_object *tbo) bo = container_of(tbo, struct radeon_bo, tbo); radeon_update_memory_usage(bo, bo->tbo.mem.mem_type, -1); - radeon_mn_unregister(bo); mutex_lock(&bo->rdev->gem.mutex); list_del_init(&bo->list); diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c index ec10533a49b8..48d97c040f49 100644 --- a/drivers/gpu/drm/radeon/radeon_vm.c +++ b/drivers/gpu/drm/radeon/radeon_vm.c @@ -493,38 +493,35 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev, } if (bo_va->it.start || bo_va->it.last) { - spin_lock(&vm->status_lock); - if (list_empty(&bo_va->vm_status)) { - /* add a clone of the bo_va to clear the old address */ - struct radeon_bo_va *tmp; - spin_unlock(&vm->status_lock); - tmp = kzalloc(sizeof(struct radeon_bo_va), GFP_KERNEL); - if (!tmp) { - mutex_unlock(&vm->mutex); - r = -ENOMEM; - goto error_unreserve; - } - tmp->it.start = bo_va->it.start; - tmp->it.last = bo_va->it.last; - tmp->vm = vm; - tmp->bo = radeon_bo_ref(bo_va->bo); - spin_lock(&vm->status_lock); - list_add(&tmp->vm_status, &vm->freed); + /* add a clone of the bo_va to clear the old address */ + struct radeon_bo_va *tmp; + tmp = kzalloc(sizeof(struct radeon_bo_va), GFP_KERNEL); + if (!tmp) { + mutex_unlock(&vm->mutex); + r = -ENOMEM; + goto error_unreserve; } - spin_unlock(&vm->status_lock); + tmp->it.start = bo_va->it.start; + tmp->it.last = bo_va->it.last; + tmp->vm = vm; + tmp->bo = radeon_bo_ref(bo_va->bo); interval_tree_remove(&bo_va->it, &vm->va); + spin_lock(&vm->status_lock); bo_va->it.start = 0; bo_va->it.last = 0; + list_del_init(&bo_va->vm_status); + list_add(&tmp->vm_status, &vm->freed); + spin_unlock(&vm->status_lock); } if (soffset || eoffset) { + spin_lock(&vm->status_lock); bo_va->it.start = soffset; bo_va->it.last = eoffset - 1; - interval_tree_insert(&bo_va->it, &vm->va); - spin_lock(&vm->status_lock); list_add(&bo_va->vm_status, &vm->cleared); spin_unlock(&vm->status_lock); + interval_tree_insert(&bo_va->it, &vm->va); } bo_va->flags = flags; @@ -1158,7 +1155,8 @@ void radeon_vm_bo_invalidate(struct radeon_device *rdev, list_for_each_entry(bo_va, &bo->va, bo_list) { spin_lock(&bo_va->vm->status_lock); - if (list_empty(&bo_va->vm_status)) + if (list_empty(&bo_va->vm_status) && + (bo_va->it.start || bo_va->it.last)) list_add(&bo_va->vm_status, &bo_va->vm->invalidated); spin_unlock(&bo_va->vm->status_lock); } diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 26388b5dd6ed..07037e32dea3 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -6466,23 +6466,27 @@ restart_ih: case 1: /* D1 vblank/vline */ switch (src_data) { case 0: /* D1 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[0]) { - drm_handle_vblank(rdev->ddev, 0); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[0])) - radeon_crtc_handle_vblank(rdev, 0); - rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D1 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[0]) { + drm_handle_vblank(rdev->ddev, 0); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[0])) + radeon_crtc_handle_vblank(rdev, 0); + rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D1 vblank\n"); + break; case 1: /* D1 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VLINE_INTERRUPT; - DRM_DEBUG("IH: D1 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VLINE_INTERRUPT; + DRM_DEBUG("IH: D1 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -6492,23 +6496,27 @@ restart_ih: case 2: /* D2 vblank/vline */ switch (src_data) { case 0: /* D2 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[1]) { - drm_handle_vblank(rdev->ddev, 1); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[1])) - radeon_crtc_handle_vblank(rdev, 1); - rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D2 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[1]) { + drm_handle_vblank(rdev->ddev, 1); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[1])) + radeon_crtc_handle_vblank(rdev, 1); + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D2 vblank\n"); + break; case 1: /* D2 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; - DRM_DEBUG("IH: D2 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; + DRM_DEBUG("IH: D2 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -6518,23 +6526,27 @@ restart_ih: case 3: /* D3 vblank/vline */ switch (src_data) { case 0: /* D3 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[2]) { - drm_handle_vblank(rdev->ddev, 2); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[2])) - radeon_crtc_handle_vblank(rdev, 2); - rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D3 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[2]) { + drm_handle_vblank(rdev->ddev, 2); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[2])) + radeon_crtc_handle_vblank(rdev, 2); + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D3 vblank\n"); + break; case 1: /* D3 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; - DRM_DEBUG("IH: D3 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; + DRM_DEBUG("IH: D3 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -6544,23 +6556,27 @@ restart_ih: case 4: /* D4 vblank/vline */ switch (src_data) { case 0: /* D4 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[3]) { - drm_handle_vblank(rdev->ddev, 3); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[3])) - radeon_crtc_handle_vblank(rdev, 3); - rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D4 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[3]) { + drm_handle_vblank(rdev->ddev, 3); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[3])) + radeon_crtc_handle_vblank(rdev, 3); + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D4 vblank\n"); + break; case 1: /* D4 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; - DRM_DEBUG("IH: D4 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; + DRM_DEBUG("IH: D4 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -6570,23 +6586,27 @@ restart_ih: case 5: /* D5 vblank/vline */ switch (src_data) { case 0: /* D5 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[4]) { - drm_handle_vblank(rdev->ddev, 4); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[4])) - radeon_crtc_handle_vblank(rdev, 4); - rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D5 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[4]) { + drm_handle_vblank(rdev->ddev, 4); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[4])) + radeon_crtc_handle_vblank(rdev, 4); + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D5 vblank\n"); + break; case 1: /* D5 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; - DRM_DEBUG("IH: D5 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; + DRM_DEBUG("IH: D5 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -6596,23 +6616,27 @@ restart_ih: case 6: /* D6 vblank/vline */ switch (src_data) { case 0: /* D6 vblank */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) { - if (rdev->irq.crtc_vblank_int[5]) { - drm_handle_vblank(rdev->ddev, 5); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (atomic_read(&rdev->irq.pflip[5])) - radeon_crtc_handle_vblank(rdev, 5); - rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; - DRM_DEBUG("IH: D6 vblank\n"); + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + if (rdev->irq.crtc_vblank_int[5]) { + drm_handle_vblank(rdev->ddev, 5); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); } + if (atomic_read(&rdev->irq.pflip[5])) + radeon_crtc_handle_vblank(rdev, 5); + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; + DRM_DEBUG("IH: D6 vblank\n"); + break; case 1: /* D6 vline */ - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; - DRM_DEBUG("IH: D6 vline\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; + DRM_DEBUG("IH: D6 vline\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); @@ -6632,88 +6656,112 @@ restart_ih: case 42: /* HPD hotplug */ switch (src_data) { case 0: - if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD1\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD1\n"); + break; case 1: - if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD2\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD2\n"); + break; case 2: - if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD3\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD3\n"); + break; case 3: - if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD4\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD4\n"); + break; case 4: - if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD5\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD5\n"); + break; case 5: - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; - queue_hotplug = true; - DRM_DEBUG("IH: HPD6\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; + queue_hotplug = true; + DRM_DEBUG("IH: HPD6\n"); + break; case 6: - if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 1\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 1\n"); + break; case 7: - if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 2\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 2\n"); + break; case 8: - if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 3\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 3\n"); + break; case 9: - if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 4\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 4\n"); + break; case 10: - if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 5\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 5\n"); + break; case 11: - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) { - rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT; - queue_dp = true; - DRM_DEBUG("IH: HPD_RX 6\n"); - } + if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT)) + DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); + + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT; + queue_dp = true; + DRM_DEBUG("IH: HPD_RX 6\n"); + break; default: DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index 1dbdf3230dae..787cd8fd897f 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -2926,6 +2926,7 @@ static struct si_dpm_quirk si_dpm_quirk_list[] = { /* PITCAIRN - https://bugs.freedesktop.org/show_bug.cgi?id=76490 */ { PCI_VENDOR_ID_ATI, 0x6810, 0x1462, 0x3036, 0, 120000 }, { PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0xe271, 0, 120000 }, + { PCI_VENDOR_ID_ATI, 0x6810, 0x174b, 0xe271, 85000, 90000 }, { 0, 0, 0, 0 }, }; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 01b558fe3695..9a0c2911272a 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -555,7 +555,6 @@ static struct platform_driver rockchip_drm_platform_driver = { .probe = rockchip_drm_platform_probe, .remove = rockchip_drm_platform_remove, .driver = { - .owner = THIS_MODULE, .name = "rockchip-drm", .of_match_table = rockchip_drm_dt_ids, .pm = &rockchip_drm_pm_ops, diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index 77d52893d40f..002645bb5bbf 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -162,7 +162,8 @@ static void rockchip_drm_output_poll_changed(struct drm_device *dev) struct rockchip_drm_private *private = dev->dev_private; struct drm_fb_helper *fb_helper = &private->fbdev_helper; - drm_fb_helper_hotplug_event(fb_helper); + if (fb_helper) + drm_fb_helper_hotplug_event(fb_helper); } static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = { diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index eb2282cc4a56..eba5f8a52fbd 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c @@ -54,55 +54,56 @@ static void rockchip_gem_free_buf(struct rockchip_gem_object *rk_obj) &rk_obj->dma_attrs); } -int rockchip_gem_mmap_buf(struct drm_gem_object *obj, - struct vm_area_struct *vma) +static int rockchip_drm_gem_object_mmap(struct drm_gem_object *obj, + struct vm_area_struct *vma) + { + int ret; struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj); struct drm_device *drm = obj->dev; - unsigned long vm_size; - vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP; - vm_size = vma->vm_end - vma->vm_start; - - if (vm_size > obj->size) - return -EINVAL; + /* + * dma_alloc_attrs() allocated a struct page table for rk_obj, so clear + * VM_PFNMAP flag that was set by drm_gem_mmap_obj()/drm_gem_mmap(). + */ + vma->vm_flags &= ~VM_PFNMAP; - return dma_mmap_attrs(drm->dev, vma, rk_obj->kvaddr, rk_obj->dma_addr, + ret = dma_mmap_attrs(drm->dev, vma, rk_obj->kvaddr, rk_obj->dma_addr, obj->size, &rk_obj->dma_attrs); + if (ret) + drm_gem_vm_close(vma); + + return ret; } -/* drm driver mmap file operations */ -int rockchip_gem_mmap(struct file *filp, struct vm_area_struct *vma) +int rockchip_gem_mmap_buf(struct drm_gem_object *obj, + struct vm_area_struct *vma) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->minor->dev; - struct drm_gem_object *obj; - struct drm_vma_offset_node *node; + struct drm_device *drm = obj->dev; int ret; - if (drm_device_is_unplugged(dev)) - return -ENODEV; + mutex_lock(&drm->struct_mutex); + ret = drm_gem_mmap_obj(obj, obj->size, vma); + mutex_unlock(&drm->struct_mutex); + if (ret) + return ret; - mutex_lock(&dev->struct_mutex); + return rockchip_drm_gem_object_mmap(obj, vma); +} - node = drm_vma_offset_exact_lookup(dev->vma_offset_manager, - vma->vm_pgoff, - vma_pages(vma)); - if (!node) { - mutex_unlock(&dev->struct_mutex); - DRM_ERROR("failed to find vma node.\n"); - return -EINVAL; - } else if (!drm_vma_node_is_allowed(node, filp)) { - mutex_unlock(&dev->struct_mutex); - return -EACCES; - } +/* drm driver mmap file operations */ +int rockchip_gem_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct drm_gem_object *obj; + int ret; - obj = container_of(node, struct drm_gem_object, vma_node); - ret = rockchip_gem_mmap_buf(obj, vma); + ret = drm_gem_mmap(filp, vma); + if (ret) + return ret; - mutex_unlock(&dev->struct_mutex); + obj = vma->vm_private_data; - return ret; + return rockchip_drm_gem_object_mmap(obj, vma); } struct rockchip_gem_object * diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index dc65161d7cad..34b78e736532 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -170,6 +170,7 @@ struct vop_win_phy { struct vop_reg enable; struct vop_reg format; + struct vop_reg rb_swap; struct vop_reg act_info; struct vop_reg dsp_info; struct vop_reg dsp_st; @@ -199,8 +200,12 @@ struct vop_data { static const uint32_t formats_01[] = { DRM_FORMAT_XRGB8888, DRM_FORMAT_ARGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_ABGR8888, DRM_FORMAT_RGB888, + DRM_FORMAT_BGR888, DRM_FORMAT_RGB565, + DRM_FORMAT_BGR565, DRM_FORMAT_NV12, DRM_FORMAT_NV16, DRM_FORMAT_NV24, @@ -209,8 +214,12 @@ static const uint32_t formats_01[] = { static const uint32_t formats_234[] = { DRM_FORMAT_XRGB8888, DRM_FORMAT_ARGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_ABGR8888, DRM_FORMAT_RGB888, + DRM_FORMAT_BGR888, DRM_FORMAT_RGB565, + DRM_FORMAT_BGR565, }; static const struct vop_win_phy win01_data = { @@ -218,6 +227,7 @@ static const struct vop_win_phy win01_data = { .nformats = ARRAY_SIZE(formats_01), .enable = VOP_REG(WIN0_CTRL0, 0x1, 0), .format = VOP_REG(WIN0_CTRL0, 0x7, 1), + .rb_swap = VOP_REG(WIN0_CTRL0, 0x1, 12), .act_info = VOP_REG(WIN0_ACT_INFO, 0x1fff1fff, 0), .dsp_info = VOP_REG(WIN0_DSP_INFO, 0x0fff0fff, 0), .dsp_st = VOP_REG(WIN0_DSP_ST, 0x1fff1fff, 0), @@ -234,6 +244,7 @@ static const struct vop_win_phy win23_data = { .nformats = ARRAY_SIZE(formats_234), .enable = VOP_REG(WIN2_CTRL0, 0x1, 0), .format = VOP_REG(WIN2_CTRL0, 0x7, 1), + .rb_swap = VOP_REG(WIN2_CTRL0, 0x1, 12), .dsp_info = VOP_REG(WIN2_DSP_INFO0, 0x0fff0fff, 0), .dsp_st = VOP_REG(WIN2_DSP_ST0, 0x1fff1fff, 0), .yrgb_mst = VOP_REG(WIN2_MST0, 0xffffffff, 0), @@ -242,15 +253,6 @@ static const struct vop_win_phy win23_data = { .dst_alpha_ctl = VOP_REG(WIN2_DST_ALPHA_CTRL, 0xff, 0), }; -static const struct vop_win_phy cursor_data = { - .data_formats = formats_234, - .nformats = ARRAY_SIZE(formats_234), - .enable = VOP_REG(HWC_CTRL0, 0x1, 0), - .format = VOP_REG(HWC_CTRL0, 0x7, 1), - .dsp_st = VOP_REG(HWC_DSP_ST, 0x1fff1fff, 0), - .yrgb_mst = VOP_REG(HWC_MST, 0xffffffff, 0), -}; - static const struct vop_ctrl ctrl_data = { .standby = VOP_REG(SYS_CTRL, 0x1, 22), .gate_en = VOP_REG(SYS_CTRL, 0x1, 23), @@ -282,14 +284,14 @@ static const struct vop_reg_data vop_init_reg_table[] = { /* * Note: rk3288 has a dedicated 'cursor' window, however, that window requires * special support to get alpha blending working. For now, just use overlay - * window 1 for the drm cursor. + * window 3 for the drm cursor. + * */ static const struct vop_win_data rk3288_vop_win_data[] = { { .base = 0x00, .phy = &win01_data, .type = DRM_PLANE_TYPE_PRIMARY }, - { .base = 0x40, .phy = &win01_data, .type = DRM_PLANE_TYPE_CURSOR }, + { .base = 0x40, .phy = &win01_data, .type = DRM_PLANE_TYPE_OVERLAY }, { .base = 0x00, .phy = &win23_data, .type = DRM_PLANE_TYPE_OVERLAY }, - { .base = 0x50, .phy = &win23_data, .type = DRM_PLANE_TYPE_OVERLAY }, - { .base = 0x00, .phy = &cursor_data, .type = DRM_PLANE_TYPE_OVERLAY }, + { .base = 0x50, .phy = &win23_data, .type = DRM_PLANE_TYPE_CURSOR }, }; static const struct vop_data rk3288_vop = { @@ -352,15 +354,32 @@ static inline void vop_mask_write_relaxed(struct vop *vop, uint32_t offset, } } +static bool has_rb_swapped(uint32_t format) +{ + switch (format) { + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_BGR888: + case DRM_FORMAT_BGR565: + return true; + default: + return false; + } +} + static enum vop_data_format vop_convert_format(uint32_t format) { switch (format) { case DRM_FORMAT_XRGB8888: case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_ABGR8888: return VOP_FMT_ARGB8888; case DRM_FORMAT_RGB888: + case DRM_FORMAT_BGR888: return VOP_FMT_RGB888; case DRM_FORMAT_RGB565: + case DRM_FORMAT_BGR565: return VOP_FMT_RGB565; case DRM_FORMAT_NV12: return VOP_FMT_YUV420SP; @@ -378,6 +397,7 @@ static bool is_alpha_support(uint32_t format) { switch (format) { case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_ABGR8888: return true; default: return false; @@ -588,6 +608,7 @@ static int vop_update_plane_event(struct drm_plane *plane, enum vop_data_format format; uint32_t val; bool is_alpha; + bool rb_swap; bool visible; int ret; struct drm_rect dest = { @@ -621,6 +642,7 @@ static int vop_update_plane_event(struct drm_plane *plane, return 0; is_alpha = is_alpha_support(fb->pixel_format); + rb_swap = has_rb_swapped(fb->pixel_format); format = vop_convert_format(fb->pixel_format); if (format < 0) return format; @@ -689,6 +711,7 @@ static int vop_update_plane_event(struct drm_plane *plane, val = (dsp_sty - 1) << 16; val |= (dsp_stx - 1) & 0xffff; VOP_WIN_SET(vop, win, dsp_st, val); + VOP_WIN_SET(vop, win, rb_swap, rb_swap); if (is_alpha) { VOP_WIN_SET(vop, win, dst_alpha_ctl, diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 882cccdad272..ac6fe40b99f7 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -490,7 +490,8 @@ pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp) else if (boot_cpu_data.x86 > 3) tmp = pgprot_noncached(tmp); #endif -#if defined(__ia64__) || defined(__arm__) || defined(__powerpc__) +#if defined(__ia64__) || defined(__arm__) || defined(__aarch64__) || \ + defined(__powerpc__) if (caching_flags & TTM_PL_FLAG_WC) tmp = pgprot_writecombine(tmp); else diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c index 3077f1554099..624d941aaad1 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c @@ -963,14 +963,13 @@ void ttm_dma_unpopulate(struct ttm_dma_tt *ttm_dma, struct device *dev) } else { pool->npages_free += count; list_splice(&ttm_dma->pages_list, &pool->free_list); - npages = count; - if (pool->npages_free > _manager->options.max_size) { + /* + * Wait to have at at least NUM_PAGES_TO_ALLOC number of pages + * to free in order to minimize calls to set_memory_wb(). + */ + if (pool->npages_free >= (_manager->options.max_size + + NUM_PAGES_TO_ALLOC)) npages = pool->npages_free - _manager->options.max_size; - /* free at least NUM_PAGES_TO_ALLOC number of pages - * to reduce calls to set_memory_wb */ - if (npages < NUM_PAGES_TO_ALLOC) - npages = NUM_PAGES_TO_ALLOC; - } } spin_unlock_irqrestore(&pool->lock, irq_flags); diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c index 6d2f39d36e44..00f2058944e5 100644 --- a/drivers/gpu/ipu-v3/ipu-common.c +++ b/drivers/gpu/ipu-v3/ipu-common.c @@ -1107,6 +1107,9 @@ static int ipu_irq_init(struct ipu_soc *ipu) return ret; } + for (i = 0; i < IPU_NUM_IRQS; i += 32) + ipu_cm_write(ipu, 0, IPU_INT_CTRL(i / 32)); + for (i = 0; i < IPU_NUM_IRQS; i += 32) { gc = irq_get_domain_generic_chip(ipu->domain, i); gc->reg_base = ipu->cm_reg; diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index f822fd2a1ada..884d82f9190e 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -546,6 +546,12 @@ static const struct hid_device_id apple_devices[] = { .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS), .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI), + .driver_data = APPLE_HAS_FN }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO), + .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS), + .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 157c62775053..e6fce23b121a 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1782,6 +1782,9 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, @@ -2463,6 +2466,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { } diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c index 3318de690e00..a2dbbbe0d8d7 100644 --- a/drivers/hid/hid-cp2112.c +++ b/drivers/hid/hid-cp2112.c @@ -356,6 +356,8 @@ static int cp2112_read(struct cp2112_device *dev, u8 *data, size_t size) struct cp2112_force_read_report report; int ret; + if (size > sizeof(dev->read_data)) + size = sizeof(dev->read_data); report.report = CP2112_DATA_READ_FORCE_SEND; report.length = cpu_to_be16(size); diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index b04b0820d816..b3b225b75d0a 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -142,6 +142,9 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI 0x0290 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO 0x0291 #define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS 0x0292 +#define USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI 0x0272 +#define USB_DEVICE_ID_APPLE_WELLSPRING9_ISO 0x0273 +#define USB_DEVICE_ID_APPLE_WELLSPRING9_JIS 0x0274 #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b #define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240 diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 6a9b05b328a9..7c811252c1ce 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -778,9 +778,16 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, /* * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN" * for the stylus. + * The check for mt_report_id ensures we don't process + * HID_DG_CONTACTCOUNT from the pen report as it is outside the physical + * collection, but within the report ID. */ if (field->physical == HID_DG_STYLUS) return 0; + else if ((field->physical == 0) && + (field->report->id != td->mt_report_id) && + (td->mt_report_id != -1)) + return 0; if (field->application == HID_DG_TOUCHSCREEN || field->application == HID_DG_TOUCHPAD) diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 53e7de7cb9e2..20f9a653444c 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -87,6 +87,9 @@ static const struct hid_blacklist { { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C05A, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C06A, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3_JP, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS }, diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 4c0ffca97bef..44958d79d598 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -1271,11 +1271,13 @@ fail_leds: pad_input_dev = NULL; wacom_wac->pad_registered = false; fail_register_pad_input: - input_unregister_device(touch_input_dev); + if (touch_input_dev) + input_unregister_device(touch_input_dev); wacom_wac->touch_input = NULL; wacom_wac->touch_registered = false; fail_register_touch_input: - input_unregister_device(pen_input_dev); + if (pen_input_dev) + input_unregister_device(pen_input_dev); wacom_wac->pen_input = NULL; wacom_wac->pen_registered = false; fail_register_pen_input: diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 232da89f4e88..0d244239e55d 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2213,6 +2213,9 @@ void wacom_setup_device_quirks(struct wacom *wacom) features->x_max = 4096; features->y_max = 4096; } + else if (features->pktlen == WACOM_PKGLEN_BBTOUCH) { + features->device_type |= WACOM_DEVICETYPE_PAD; + } } /* diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c index 37c16afe007a..c8487894b312 100644 --- a/drivers/hwmon/dell-smm-hwmon.c +++ b/drivers/hwmon/dell-smm-hwmon.c @@ -929,6 +929,21 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = { MODULE_DEVICE_TABLE(dmi, i8k_dmi_table); +static struct dmi_system_id i8k_blacklist_dmi_table[] __initdata = { + { + /* + * CPU fan speed going up and down on Dell Studio XPS 8100 + * for unknown reasons. + */ + .ident = "Dell Studio XPS 8100", + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Studio XPS 8100"), + }, + }, + { } +}; + /* * Probe for the presence of a supported laptop. */ @@ -940,7 +955,8 @@ static int __init i8k_probe(void) /* * Get DMI information */ - if (!dmi_check_system(i8k_dmi_table)) { + if (!dmi_check_system(i8k_dmi_table) || + dmi_check_system(i8k_blacklist_dmi_table)) { if (!ignore_dmi && !force) return -ENODEV; diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c index 9b55e673b67c..85d106fe3ce8 100644 --- a/drivers/hwmon/g762.c +++ b/drivers/hwmon/g762.c @@ -582,6 +582,7 @@ static const struct of_device_id g762_dt_match[] = { { .compatible = "gmt,g763" }, { }, }; +MODULE_DEVICE_TABLE(of, g762_dt_match); /* * Grab clock (a required property), enable it, get (fixed) clock frequency diff --git a/drivers/hwmon/nct7802.c b/drivers/hwmon/nct7802.c index 28fcb2e246d5..fbfc02bb2cfa 100644 --- a/drivers/hwmon/nct7802.c +++ b/drivers/hwmon/nct7802.c @@ -195,7 +195,7 @@ abort: } static int nct7802_write_voltage(struct nct7802_data *data, int nr, int index, - unsigned int voltage) + unsigned long voltage) { int shift = 8 - REG_VOLTAGE_LIMIT_MSB_SHIFT[index - 1][nr]; int err; diff --git a/drivers/hwmon/nct7904.c b/drivers/hwmon/nct7904.c index b77b82f24480..08ff89d222e5 100644 --- a/drivers/hwmon/nct7904.c +++ b/drivers/hwmon/nct7904.c @@ -412,8 +412,9 @@ static ssize_t show_pwm(struct device *dev, return sprintf(buf, "%d\n", val); } -static ssize_t store_mode(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) +static ssize_t store_enable(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) { int index = to_sensor_dev_attr(devattr)->index; struct nct7904_data *data = dev_get_drvdata(dev); @@ -422,18 +423,18 @@ static ssize_t store_mode(struct device *dev, struct device_attribute *devattr, if (kstrtoul(buf, 10, &val) < 0) return -EINVAL; - if (val > 1 || (val && !data->fan_mode[index])) + if (val < 1 || val > 2 || (val == 2 && !data->fan_mode[index])) return -EINVAL; ret = nct7904_write_reg(data, BANK_3, FANCTL1_FMR_REG + index, - val ? data->fan_mode[index] : 0); + val == 2 ? data->fan_mode[index] : 0); return ret ? ret : count; } -/* Return 0 for manual mode or 1 for SmartFan mode */ -static ssize_t show_mode(struct device *dev, - struct device_attribute *devattr, char *buf) +/* Return 1 for manual mode or 2 for SmartFan mode */ +static ssize_t show_enable(struct device *dev, + struct device_attribute *devattr, char *buf) { int index = to_sensor_dev_attr(devattr)->index; struct nct7904_data *data = dev_get_drvdata(dev); @@ -443,36 +444,36 @@ static ssize_t show_mode(struct device *dev, if (val < 0) return val; - return sprintf(buf, "%d\n", val ? 1 : 0); + return sprintf(buf, "%d\n", val ? 2 : 1); } /* 2 attributes per channel: pwm and mode */ -static SENSOR_DEVICE_ATTR(fan1_pwm, S_IRUGO | S_IWUSR, +static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 0); -static SENSOR_DEVICE_ATTR(fan1_mode, S_IRUGO | S_IWUSR, - show_mode, store_mode, 0); -static SENSOR_DEVICE_ATTR(fan2_pwm, S_IRUGO | S_IWUSR, +static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, + show_enable, store_enable, 0); +static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 1); -static SENSOR_DEVICE_ATTR(fan2_mode, S_IRUGO | S_IWUSR, - show_mode, store_mode, 1); -static SENSOR_DEVICE_ATTR(fan3_pwm, S_IRUGO | S_IWUSR, +static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, + show_enable, store_enable, 1); +static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 2); -static SENSOR_DEVICE_ATTR(fan3_mode, S_IRUGO | S_IWUSR, - show_mode, store_mode, 2); -static SENSOR_DEVICE_ATTR(fan4_pwm, S_IRUGO | S_IWUSR, +static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, + show_enable, store_enable, 2); +static SENSOR_DEVICE_ATTR(pwm4, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 3); -static SENSOR_DEVICE_ATTR(fan4_mode, S_IRUGO | S_IWUSR, - show_mode, store_mode, 3); +static SENSOR_DEVICE_ATTR(pwm4_enable, S_IRUGO | S_IWUSR, + show_enable, store_enable, 3); static struct attribute *nct7904_fanctl_attrs[] = { - &sensor_dev_attr_fan1_pwm.dev_attr.attr, - &sensor_dev_attr_fan1_mode.dev_attr.attr, - &sensor_dev_attr_fan2_pwm.dev_attr.attr, - &sensor_dev_attr_fan2_mode.dev_attr.attr, - &sensor_dev_attr_fan3_pwm.dev_attr.attr, - &sensor_dev_attr_fan3_mode.dev_attr.attr, - &sensor_dev_attr_fan4_pwm.dev_attr.attr, - &sensor_dev_attr_fan4_mode.dev_attr.attr, + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm1_enable.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm2_enable.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm3_enable.dev_attr.attr, + &sensor_dev_attr_pwm4.dev_attr.attr, + &sensor_dev_attr_pwm4_enable.dev_attr.attr, NULL }; @@ -574,6 +575,7 @@ static const struct i2c_device_id nct7904_id[] = { {"nct7904", 0}, {} }; +MODULE_DEVICE_TABLE(i2c, nct7904_id); static struct i2c_driver nct7904_driver = { .class = I2C_CLASS_HWMON, diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 35ac23768ce9..577d58d1f1a1 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -633,6 +633,7 @@ config I2C_MPC config I2C_MT65XX tristate "MediaTek I2C adapter" depends on ARCH_MEDIATEK || COMPILE_TEST + depends on HAS_DMA help This selects the MediaTek(R) Integrated Inter Circuit bus driver for MT65xx and MT81xx. diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index af162b4c7a6d..025686d41640 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c @@ -692,7 +692,7 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, iface); - dev_info(&pdev->dev, "Blackfin BF5xx on-chip I2C TWI Contoller, " + dev_info(&pdev->dev, "Blackfin BF5xx on-chip I2C TWI Controller, " "regs_base@%p\n", iface->regs_base); return 0; @@ -735,6 +735,6 @@ subsys_initcall(i2c_bfin_twi_init); module_exit(i2c_bfin_twi_exit); MODULE_AUTHOR("Bryan Wu, Sonic Zhang"); -MODULE_DESCRIPTION("Blackfin BF5xx on-chip I2C TWI Contoller Driver"); +MODULE_DESCRIPTION("Blackfin BF5xx on-chip I2C TWI Controller Driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:i2c-bfin-twi"); diff --git a/drivers/i2c/busses/i2c-jz4780.c b/drivers/i2c/busses/i2c-jz4780.c index 19b2d689a5ef..f325663c27c5 100644 --- a/drivers/i2c/busses/i2c-jz4780.c +++ b/drivers/i2c/busses/i2c-jz4780.c @@ -764,12 +764,15 @@ static int jz4780_i2c_probe(struct platform_device *pdev) if (IS_ERR(i2c->clk)) return PTR_ERR(i2c->clk); - clk_prepare_enable(i2c->clk); + ret = clk_prepare_enable(i2c->clk); + if (ret) + return ret; - if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", - &clk_freq)) { + ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", + &clk_freq); + if (ret) { dev_err(&pdev->dev, "clock-frequency not specified in DT"); - return clk_freq; + goto err; } i2c->speed = clk_freq / 1000; @@ -790,10 +793,8 @@ static int jz4780_i2c_probe(struct platform_device *pdev) i2c->irq = platform_get_irq(pdev, 0); ret = devm_request_irq(&pdev->dev, i2c->irq, jz4780_i2c_irq, 0, dev_name(&pdev->dev), i2c); - if (ret) { - ret = -ENODEV; + if (ret) goto err; - } ret = i2c_add_adapter(&i2c->adap); if (ret < 0) { diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index d1c22e3fdd14..fc9bf7f30e35 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1247,7 +1247,14 @@ static void omap_i2c_prepare_recovery(struct i2c_adapter *adap) u32 reg; reg = omap_i2c_read_reg(dev, OMAP_I2C_SYSTEST_REG); + /* enable test mode */ reg |= OMAP_I2C_SYSTEST_ST_EN; + /* select SDA/SCL IO mode */ + reg |= 3 << OMAP_I2C_SYSTEST_TMODE_SHIFT; + /* set SCL to high-impedance state (reset value is 0) */ + reg |= OMAP_I2C_SYSTEST_SCL_O; + /* set SDA to high-impedance state (reset value is 0) */ + reg |= OMAP_I2C_SYSTEST_SDA_O; omap_i2c_write_reg(dev, OMAP_I2C_SYSTEST_REG, reg); } @@ -1257,7 +1264,11 @@ static void omap_i2c_unprepare_recovery(struct i2c_adapter *adap) u32 reg; reg = omap_i2c_read_reg(dev, OMAP_I2C_SYSTEST_REG); + /* restore reset values */ reg &= ~OMAP_I2C_SYSTEST_ST_EN; + reg &= ~OMAP_I2C_SYSTEST_TMODE_MASK; + reg &= ~OMAP_I2C_SYSTEST_SCL_O; + reg &= ~OMAP_I2C_SYSTEST_SDA_O; omap_i2c_write_reg(dev, OMAP_I2C_SYSTEST_REG, reg); } diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c index dcca7076231e..1c9cb65ac4cf 100644 --- a/drivers/i2c/busses/i2c-xgene-slimpro.c +++ b/drivers/i2c/busses/i2c-xgene-slimpro.c @@ -419,6 +419,7 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev) rc = i2c_add_adapter(adapter); if (rc) { dev_err(&pdev->dev, "Adapter registeration failed\n"); + mbox_free_channel(ctx->mbox_chan); return rc; } diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 069a41f116dd..c83e4d13cfc5 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -567,6 +567,9 @@ static int i2c_generic_recovery(struct i2c_adapter *adap) if (bri->prepare_recovery) bri->prepare_recovery(adap); + bri->set_scl(adap, val); + ndelay(RECOVERY_NDELAY); + /* * By this time SCL is high, as we need to give 9 falling-rising edges */ @@ -597,7 +600,6 @@ static int i2c_generic_recovery(struct i2c_adapter *adap) int i2c_generic_scl_recovery(struct i2c_adapter *adap) { - adap->bus_recovery_info->set_scl(adap, 1); return i2c_generic_recovery(adap); } EXPORT_SYMBOL_GPL(i2c_generic_scl_recovery); @@ -1012,6 +1014,8 @@ EXPORT_SYMBOL_GPL(i2c_new_device); */ void i2c_unregister_device(struct i2c_client *client) { + if (client->dev.of_node) + of_node_clear_flag(client->dev.of_node, OF_POPULATED); device_unregister(&client->dev); } EXPORT_SYMBOL_GPL(i2c_unregister_device); @@ -1320,8 +1324,11 @@ static void of_i2c_register_devices(struct i2c_adapter *adap) dev_dbg(&adap->dev, "of_i2c: walking child nodes\n"); - for_each_available_child_of_node(adap->dev.of_node, node) + for_each_available_child_of_node(adap->dev.of_node, node) { + if (of_node_test_and_set_flag(node, OF_POPULATED)) + continue; of_i2c_register_device(adap, node); + } } static int of_dev_node_match(struct device *dev, void *data) @@ -1333,13 +1340,17 @@ static int of_dev_node_match(struct device *dev, void *data) struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) { struct device *dev; + struct i2c_client *client; - dev = bus_find_device(&i2c_bus_type, NULL, node, - of_dev_node_match); + dev = bus_find_device(&i2c_bus_type, NULL, node, of_dev_node_match); if (!dev) return NULL; - return i2c_verify_client(dev); + client = i2c_verify_client(dev); + if (!client) + put_device(dev); + + return client; } EXPORT_SYMBOL(of_find_i2c_device_by_node); @@ -1347,13 +1358,17 @@ EXPORT_SYMBOL(of_find_i2c_device_by_node); struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node) { struct device *dev; + struct i2c_adapter *adapter; - dev = bus_find_device(&i2c_bus_type, NULL, node, - of_dev_node_match); + dev = bus_find_device(&i2c_bus_type, NULL, node, of_dev_node_match); if (!dev) return NULL; - return i2c_verify_adapter(dev); + adapter = i2c_verify_adapter(dev); + if (!adapter) + put_device(dev); + + return adapter; } EXPORT_SYMBOL(of_find_i2c_adapter_by_node); #else @@ -1853,6 +1868,11 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action, if (adap == NULL) return NOTIFY_OK; /* not for us */ + if (of_node_test_and_set_flag(rd->dn, OF_POPULATED)) { + put_device(&adap->dev); + return NOTIFY_OK; + } + client = of_i2c_register_device(adap, rd->dn); put_device(&adap->dev); @@ -1863,6 +1883,10 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action, } break; case OF_RECONFIG_CHANGE_REMOVE: + /* already depopulated? */ + if (!of_node_check_flag(rd->dn, OF_POPULATED)) + return NOTIFY_OK; + /* find our device by node */ client = of_find_i2c_device_by_node(rd->dn); if (client == NULL) diff --git a/drivers/i2c/i2c-slave-eeprom.c b/drivers/i2c/i2c-slave-eeprom.c index 822374654609..1da449614779 100644 --- a/drivers/i2c/i2c-slave-eeprom.c +++ b/drivers/i2c/i2c-slave-eeprom.c @@ -80,9 +80,6 @@ static ssize_t i2c_slave_eeprom_bin_read(struct file *filp, struct kobject *kobj struct eeprom_data *eeprom; unsigned long flags; - if (off + count > attr->size) - return -EFBIG; - eeprom = dev_get_drvdata(container_of(kobj, struct device, kobj)); spin_lock_irqsave(&eeprom->buffer_lock, flags); @@ -98,9 +95,6 @@ static ssize_t i2c_slave_eeprom_bin_write(struct file *filp, struct kobject *kob struct eeprom_data *eeprom; unsigned long flags; - if (off + count > attr->size) - return -EFBIG; - eeprom = dev_get_drvdata(container_of(kobj, struct device, kobj)); spin_lock_irqsave(&eeprom->buffer_lock, flags); diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c index a7b66edf2a38..0104cdef8709 100644 --- a/drivers/iio/accel/bmc150-accel.c +++ b/drivers/iio/accel/bmc150-accel.c @@ -1407,7 +1407,7 @@ static void bmc150_accel_unregister_triggers(struct bmc150_accel_data *data, { int i; - for (i = from; i >= 0; i++) { + for (i = from; i >= 0; i--) { if (data->triggers[i].indio_trig) { iio_trigger_unregister(data->triggers[i].indio_trig); data->triggers[i].indio_trig = NULL; diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 85283eab2ea7..b921d84c1be6 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -583,21 +583,21 @@ static void mma8452_transient_interrupt(struct iio_dev *indio_dev) if (src & MMA8452_TRANSIENT_SRC_XTRANSE) iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X, - IIO_EV_TYPE_THRESH, + IIO_EV_TYPE_MAG, IIO_EV_DIR_RISING), ts); if (src & MMA8452_TRANSIENT_SRC_YTRANSE) iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_Y, - IIO_EV_TYPE_THRESH, + IIO_EV_TYPE_MAG, IIO_EV_DIR_RISING), ts); if (src & MMA8452_TRANSIENT_SRC_ZTRANSE) iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_Z, - IIO_EV_TYPE_THRESH, + IIO_EV_TYPE_MAG, IIO_EV_DIR_RISING), ts); } @@ -671,7 +671,7 @@ static int mma8452_reg_access_dbg(struct iio_dev *indio_dev, static const struct iio_event_spec mma8452_transient_event[] = { { - .type = IIO_EV_TYPE_THRESH, + .type = IIO_EV_TYPE_MAG, .dir = IIO_EV_DIR_RISING, .mask_separate = BIT(IIO_EV_INFO_ENABLE), .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) | diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 2714f043fa6c..50c103d75af9 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -163,8 +163,7 @@ config DA9150_GPADC config CC10001_ADC tristate "Cosmic Circuits 10001 ADC driver" - depends on HAVE_CLK || REGULATOR - depends on HAS_IOMEM + depends on HAS_IOMEM && HAVE_CLK && REGULATOR select IIO_BUFFER select IIO_TRIGGERED_BUFFER help diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 8a0eb4a04fb5..7b40925dd4ff 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -182,7 +182,7 @@ struct at91_adc_caps { u8 ts_pen_detect_sensitivity; /* startup time calculate function */ - u32 (*calc_startup_ticks)(u8 startup_time, u32 adc_clk_khz); + u32 (*calc_startup_ticks)(u32 startup_time, u32 adc_clk_khz); u8 num_channels; struct at91_adc_reg_desc registers; @@ -201,7 +201,7 @@ struct at91_adc_state { u8 num_channels; void __iomem *reg_base; struct at91_adc_reg_desc *registers; - u8 startup_time; + u32 startup_time; u8 sample_hold_time; bool sleep_mode; struct iio_trigger **trig; @@ -779,7 +779,7 @@ ret: return ret; } -static u32 calc_startup_ticks_9260(u8 startup_time, u32 adc_clk_khz) +static u32 calc_startup_ticks_9260(u32 startup_time, u32 adc_clk_khz) { /* * Number of ticks needed to cover the startup time of the ADC @@ -790,7 +790,7 @@ static u32 calc_startup_ticks_9260(u8 startup_time, u32 adc_clk_khz) return round_up((startup_time * adc_clk_khz / 1000) - 1, 8) / 8; } -static u32 calc_startup_ticks_9x5(u8 startup_time, u32 adc_clk_khz) +static u32 calc_startup_ticks_9x5(u32 startup_time, u32 adc_clk_khz) { /* * For sama5d3x and at91sam9x5, the formula changes to: diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c index 72969c8a0a51..b19e4f9d16e0 100644 --- a/drivers/iio/adc/mcp320x.c +++ b/drivers/iio/adc/mcp320x.c @@ -309,6 +309,8 @@ static int mcp320x_probe(struct spi_device *spi) indio_dev->channels = chip_info->channels; indio_dev->num_channels = chip_info->num_channels; + adc->chip_info = chip_info; + adc->transfer[0].tx_buf = &adc->tx_buf; adc->transfer[0].len = sizeof(adc->tx_buf); adc->transfer[1].rx_buf = adc->rx_buf; diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c index 8d4e019ea4ca..9c311c1e1ac7 100644 --- a/drivers/iio/adc/rockchip_saradc.c +++ b/drivers/iio/adc/rockchip_saradc.c @@ -349,3 +349,7 @@ static struct platform_driver rockchip_saradc_driver = { }; module_platform_driver(rockchip_saradc_driver); + +MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>"); +MODULE_DESCRIPTION("Rockchip SARADC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c index 06f4792240f0..ebe415f10640 100644 --- a/drivers/iio/adc/twl4030-madc.c +++ b/drivers/iio/adc/twl4030-madc.c @@ -833,7 +833,8 @@ static int twl4030_madc_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, twl4030_madc_threaded_irq_handler, - IRQF_TRIGGER_RISING, "twl4030_madc", madc); + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "twl4030_madc", madc); if (ret) { dev_err(&pdev->dev, "could not request irq\n"); goto err_i2c; diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c index 23b8fb94ec09..6bf4c20eb231 100644 --- a/drivers/iio/adc/vf610_adc.c +++ b/drivers/iio/adc/vf610_adc.c @@ -701,7 +701,7 @@ static int vf610_adc_reg_access(struct iio_dev *indio_dev, struct vf610_adc *info = iio_priv(indio_dev); if ((readval == NULL) || - (!(reg % 4) || (reg > VF610_REG_ADC_PCTL))) + ((reg % 4) || (reg > VF610_REG_ADC_PCTL))) return -EINVAL; *readval = readl(info->regs + reg); diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c index 610fc98f88ef..595511022795 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c @@ -36,6 +36,8 @@ static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state) s32 poll_value = 0; if (state) { + if (!atomic_read(&st->user_requested_state)) + return 0; if (sensor_hub_device_open(st->hsdev)) return -EIO; @@ -52,8 +54,12 @@ static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state) poll_value = hid_sensor_read_poll_value(st); } else { - if (!atomic_dec_and_test(&st->data_ready)) + int val; + + val = atomic_dec_if_positive(&st->data_ready); + if (val < 0) return 0; + sensor_hub_device_close(st->hsdev); state_val = hid_sensor_get_usage_index(st->hsdev, st->power_state.report_id, @@ -92,9 +98,11 @@ EXPORT_SYMBOL(hid_sensor_power_state); int hid_sensor_power_state(struct hid_sensor_common *st, bool state) { + #ifdef CONFIG_PM int ret; + atomic_set(&st->user_requested_state, state); if (state) ret = pm_runtime_get_sync(&st->pdev->dev); else { @@ -109,6 +117,7 @@ int hid_sensor_power_state(struct hid_sensor_common *st, bool state) return 0; #else + atomic_set(&st->user_requested_state, state); return _hid_sensor_power_state(st, state); #endif } diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c index 61bb9d4239ea..e98428df0d44 100644 --- a/drivers/iio/dac/ad5624r_spi.c +++ b/drivers/iio/dac/ad5624r_spi.c @@ -22,7 +22,7 @@ #include "ad5624r.h" static int ad5624r_spi_write(struct spi_device *spi, - u8 cmd, u8 addr, u16 val, u8 len) + u8 cmd, u8 addr, u16 val, u8 shift) { u32 data; u8 msg[3]; @@ -35,7 +35,7 @@ static int ad5624r_spi_write(struct spi_device *spi, * 14-, 12-bit input code followed by 0, 2, or 4 don't care bits, * for the AD5664R, AD5644R, and AD5624R, respectively. */ - data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << (16 - len)); + data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << shift); msg[0] = data >> 16; msg[1] = data >> 8; msg[2] = data; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index ca6de8e2d0f9..f0e06093b5e8 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -431,6 +431,23 @@ static int inv_mpu6050_write_gyro_scale(struct inv_mpu6050_state *st, int val) return -EINVAL; } +static int inv_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ANGL_VEL: + return IIO_VAL_INT_PLUS_NANO; + default: + return IIO_VAL_INT_PLUS_MICRO; + } + default: + return IIO_VAL_INT_PLUS_MICRO; + } + + return -EINVAL; +} static int inv_mpu6050_write_accel_scale(struct inv_mpu6050_state *st, int val) { int result, i; @@ -702,6 +719,7 @@ static const struct iio_info mpu_info = { .driver_module = THIS_MODULE, .read_raw = &inv_mpu6050_read_raw, .write_raw = &inv_mpu6050_write_raw, + .write_raw_get_fmt = &inv_write_raw_get_fmt, .attrs = &inv_attribute_group, .validate_trigger = inv_mpu6050_validate_trigger, }; diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index a459341a79f9..7ed859a700c4 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -199,6 +199,7 @@ config SENSORS_LM3533 config LTR501 tristate "LTR-501ALS-01 light sensor" depends on I2C + select REGMAP_I2C select IIO_BUFFER select IIO_TRIGGERED_BUFFER help @@ -233,6 +234,7 @@ config PA12203001 config STK3310 tristate "STK3310 ALS and proximity sensor" depends on I2C + select REGMAP_I2C help Say yes here to get support for the Sensortek STK3310 ambient light and proximity sensor. The STK3311 model is also supported by this diff --git a/drivers/iio/light/cm3323.c b/drivers/iio/light/cm3323.c index 54c9e2df43f2..d823c112d54b 100644 --- a/drivers/iio/light/cm3323.c +++ b/drivers/iio/light/cm3323.c @@ -123,7 +123,7 @@ static int cm3323_set_it_bits(struct cm3323_data *data, int val, int val2) for (i = 0; i < ARRAY_SIZE(cm3323_int_time); i++) { if (val == cm3323_int_time[i].val && val2 == cm3323_int_time[i].val2) { - reg_conf = data->reg_conf; + reg_conf = data->reg_conf & ~CM3323_CONF_IT_MASK; reg_conf |= i << CM3323_CONF_IT_SHIFT; ret = i2c_smbus_write_word_data(data->client, diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index f4c9a5cdfed6..809a961b9a7f 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -1302,7 +1302,7 @@ static int ltr501_init(struct ltr501_data *data) if (ret < 0) return ret; - data->als_contr = ret | data->chip_info->als_mode_active; + data->als_contr = status | data->chip_info->als_mode_active; ret = regmap_read(data->regmap, LTR501_PS_CONTR, &status); if (ret < 0) diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c index d26b931730ee..f101bb5bddc7 100644 --- a/drivers/iio/light/stk3310.c +++ b/drivers/iio/light/stk3310.c @@ -43,7 +43,6 @@ #define STK3311_CHIP_ID_VAL 0x1D #define STK3310_PSINT_EN 0x01 #define STK3310_PS_MAX_VAL 0xFFFF -#define STK3310_THRESH_MAX 0xFFFF #define STK3310_DRIVER_NAME "stk3310" #define STK3310_REGMAP_NAME "stk3310_regmap" @@ -84,15 +83,13 @@ static const struct reg_field stk3310_reg_field_flag_psint = REG_FIELD(STK3310_REG_FLAG, 4, 4); static const struct reg_field stk3310_reg_field_flag_nf = REG_FIELD(STK3310_REG_FLAG, 0, 0); -/* - * Maximum PS values with regard to scale. Used to export the 'inverse' - * PS value (high values for far objects, low values for near objects). - */ + +/* Estimate maximum proximity values with regard to measurement scale. */ static const int stk3310_ps_max[4] = { - STK3310_PS_MAX_VAL / 64, - STK3310_PS_MAX_VAL / 16, - STK3310_PS_MAX_VAL / 4, - STK3310_PS_MAX_VAL, + STK3310_PS_MAX_VAL / 640, + STK3310_PS_MAX_VAL / 160, + STK3310_PS_MAX_VAL / 40, + STK3310_PS_MAX_VAL / 10 }; static const int stk3310_scale_table[][2] = { @@ -128,14 +125,14 @@ static const struct iio_event_spec stk3310_events[] = { /* Proximity event */ { .type = IIO_EV_TYPE_THRESH, - .dir = IIO_EV_DIR_FALLING, + .dir = IIO_EV_DIR_RISING, .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), }, /* Out-of-proximity event */ { .type = IIO_EV_TYPE_THRESH, - .dir = IIO_EV_DIR_RISING, + .dir = IIO_EV_DIR_FALLING, .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), }, @@ -203,25 +200,18 @@ static int stk3310_read_event(struct iio_dev *indio_dev, int *val, int *val2) { u8 reg; - u16 buf; + __be16 buf; int ret; - unsigned int index; struct stk3310_data *data = iio_priv(indio_dev); if (info != IIO_EV_INFO_VALUE) return -EINVAL; - /* - * Only proximity interrupts are implemented at the moment. - * Since we're inverting proximity values, the sensor's 'high' - * threshold will become our 'low' threshold, associated with - * 'near' events. Similarly, the sensor's 'low' threshold will - * be our 'high' threshold, associated with 'far' events. - */ + /* Only proximity interrupts are implemented at the moment. */ if (dir == IIO_EV_DIR_RISING) - reg = STK3310_REG_THDL_PS; - else if (dir == IIO_EV_DIR_FALLING) reg = STK3310_REG_THDH_PS; + else if (dir == IIO_EV_DIR_FALLING) + reg = STK3310_REG_THDL_PS; else return -EINVAL; @@ -232,8 +222,7 @@ static int stk3310_read_event(struct iio_dev *indio_dev, dev_err(&data->client->dev, "register read failed\n"); return ret; } - regmap_field_read(data->reg_ps_gain, &index); - *val = swab16(stk3310_ps_max[index] - buf); + *val = be16_to_cpu(buf); return IIO_VAL_INT; } @@ -246,7 +235,7 @@ static int stk3310_write_event(struct iio_dev *indio_dev, int val, int val2) { u8 reg; - u16 buf; + __be16 buf; int ret; unsigned int index; struct stk3310_data *data = iio_priv(indio_dev); @@ -257,13 +246,13 @@ static int stk3310_write_event(struct iio_dev *indio_dev, return -EINVAL; if (dir == IIO_EV_DIR_RISING) - reg = STK3310_REG_THDL_PS; - else if (dir == IIO_EV_DIR_FALLING) reg = STK3310_REG_THDH_PS; + else if (dir == IIO_EV_DIR_FALLING) + reg = STK3310_REG_THDL_PS; else return -EINVAL; - buf = swab16(stk3310_ps_max[index] - val); + buf = cpu_to_be16(val); ret = regmap_bulk_write(data->regmap, reg, &buf, 2); if (ret < 0) dev_err(&client->dev, "failed to set PS threshold!\n"); @@ -312,7 +301,7 @@ static int stk3310_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { u8 reg; - u16 buf; + __be16 buf; int ret; unsigned int index; struct stk3310_data *data = iio_priv(indio_dev); @@ -333,15 +322,7 @@ static int stk3310_read_raw(struct iio_dev *indio_dev, mutex_unlock(&data->lock); return ret; } - *val = swab16(buf); - if (chan->type == IIO_PROXIMITY) { - /* - * Invert the proximity data so we return low values - * for close objects and high values for far ones. - */ - regmap_field_read(data->reg_ps_gain, &index); - *val = stk3310_ps_max[index] - *val; - } + *val = be16_to_cpu(buf); mutex_unlock(&data->lock); return IIO_VAL_INT; case IIO_CHAN_INFO_INT_TIME: @@ -581,8 +562,8 @@ static irqreturn_t stk3310_irq_event_handler(int irq, void *private) } event = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 1, IIO_EV_TYPE_THRESH, - (dir ? IIO_EV_DIR_RISING : - IIO_EV_DIR_FALLING)); + (dir ? IIO_EV_DIR_FALLING : + IIO_EV_DIR_RISING)); iio_push_event(indio_dev, event, data->timestamp); /* Reset the interrupt flag */ @@ -627,13 +608,7 @@ static int stk3310_probe(struct i2c_client *client, if (ret < 0) return ret; - ret = iio_device_register(indio_dev); - if (ret < 0) { - dev_err(&client->dev, "device_register failed\n"); - stk3310_set_state(data, STK3310_STATE_STANDBY); - } - - if (client->irq <= 0) + if (client->irq < 0) client->irq = stk3310_gpio_probe(client); if (client->irq >= 0) { @@ -648,6 +623,12 @@ static int stk3310_probe(struct i2c_client *client, client->irq); } + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&client->dev, "device_register failed\n"); + stk3310_set_state(data, STK3310_STATE_STANDBY); + } + return ret; } diff --git a/drivers/iio/light/tcs3414.c b/drivers/iio/light/tcs3414.c index 8075388aa672..f90f8c5919fe 100644 --- a/drivers/iio/light/tcs3414.c +++ b/drivers/iio/light/tcs3414.c @@ -185,7 +185,7 @@ static int tcs3414_write_raw(struct iio_dev *indio_dev, if (val != 0) return -EINVAL; for (i = 0; i < ARRAY_SIZE(tcs3414_times); i++) { - if (val == tcs3414_times[i] * 1000) { + if (val2 == tcs3414_times[i] * 1000) { data->timing &= ~TCS3414_INTEG_MASK; data->timing |= i; return i2c_smbus_write_byte_data( diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index dcadfc4f0661..efb9350b0d76 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig @@ -90,6 +90,7 @@ config IIO_ST_MAGN_SPI_3AXIS config BMC150_MAGN tristate "Bosch BMC150 Magnetometer Driver" depends on I2C + select REGMAP_I2C select IIO_BUFFER select IIO_TRIGGERED_BUFFER help diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c index bf47c8838b49..e330205f8194 100644 --- a/drivers/iio/magnetometer/bmc150_magn.c +++ b/drivers/iio/magnetometer/bmc150_magn.c @@ -697,11 +697,11 @@ static int bmc150_magn_init(struct bmc150_magn_data *data) goto err_poweroff; } if (chip_id != BMC150_MAGN_CHIP_ID_VAL) { - dev_err(&data->client->dev, "Invalid chip id 0x%x\n", ret); + dev_err(&data->client->dev, "Invalid chip id 0x%x\n", chip_id); ret = -ENODEV; goto err_poweroff; } - dev_dbg(&data->client->dev, "Chip id %x\n", ret); + dev_dbg(&data->client->dev, "Chip id %x\n", chip_id); preset = bmc150_magn_presets_table[BMC150_MAGN_DEFAULT_PRESET]; ret = bmc150_magn_set_odr(data, preset.odr); diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c index fa4ccd070e56..176e14a61558 100644 --- a/drivers/iio/magnetometer/mmc35240.c +++ b/drivers/iio/magnetometer/mmc35240.c @@ -84,10 +84,10 @@ #define MMC35240_OTP_START_ADDR 0x1B enum mmc35240_resolution { - MMC35240_16_BITS_SLOW = 0, /* 100 Hz */ - MMC35240_16_BITS_FAST, /* 200 Hz */ - MMC35240_14_BITS, /* 333 Hz */ - MMC35240_12_BITS, /* 666 Hz */ + MMC35240_16_BITS_SLOW = 0, /* 7.92 ms */ + MMC35240_16_BITS_FAST, /* 4.08 ms */ + MMC35240_14_BITS, /* 2.16 ms */ + MMC35240_12_BITS, /* 1.20 ms */ }; enum mmc35240_axis { @@ -100,22 +100,22 @@ static const struct { int sens[3]; /* sensitivity per X, Y, Z axis */ int nfo; /* null field output */ } mmc35240_props_table[] = { - /* 16 bits, 100Hz ODR */ + /* 16 bits, 125Hz ODR */ { {1024, 1024, 1024}, 32768, }, - /* 16 bits, 200Hz ODR */ + /* 16 bits, 250Hz ODR */ { {1024, 1024, 770}, 32768, }, - /* 14 bits, 333Hz ODR */ + /* 14 bits, 450Hz ODR */ { {256, 256, 193}, 8192, }, - /* 12 bits, 666Hz ODR */ + /* 12 bits, 800Hz ODR */ { {64, 64, 48}, 2048, @@ -133,9 +133,15 @@ struct mmc35240_data { int axis_scale[3]; }; -static const int mmc35240_samp_freq[] = {100, 200, 333, 666}; +static const struct { + int val; + int val2; +} mmc35240_samp_freq[] = { {1, 500000}, + {13, 0}, + {25, 0}, + {50, 0} }; -static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100 200 333 666"); +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("1.5 13 25 50"); #define MMC35240_CHANNEL(_axis) { \ .type = IIO_MAGN, \ @@ -168,7 +174,8 @@ static int mmc35240_get_samp_freq_index(struct mmc35240_data *data, int i; for (i = 0; i < ARRAY_SIZE(mmc35240_samp_freq); i++) - if (mmc35240_samp_freq[i] == val) + if (mmc35240_samp_freq[i].val == val && + mmc35240_samp_freq[i].val2 == val2) return i; return -EINVAL; } @@ -195,8 +202,8 @@ static int mmc35240_hw_set(struct mmc35240_data *data, bool set) coil_bit = MMC35240_CTRL0_RESET_BIT; return regmap_update_bits(data->regmap, MMC35240_REG_CTRL0, - MMC35240_CTRL0_REFILL_BIT, - coil_bit); + coil_bit, coil_bit); + } static int mmc35240_init(struct mmc35240_data *data) @@ -215,14 +222,15 @@ static int mmc35240_init(struct mmc35240_data *data) /* * make sure we restore sensor characteristics, by doing - * a RESET/SET sequence + * a SET/RESET sequence, the axis polarity being naturally + * aligned after RESET */ - ret = mmc35240_hw_set(data, false); + ret = mmc35240_hw_set(data, true); if (ret < 0) return ret; usleep_range(MMC53240_WAIT_SET_RESET, MMC53240_WAIT_SET_RESET + 1); - ret = mmc35240_hw_set(data, true); + ret = mmc35240_hw_set(data, false); if (ret < 0) return ret; @@ -378,9 +386,9 @@ static int mmc35240_read_raw(struct iio_dev *indio_dev, if (i < 0 || i >= ARRAY_SIZE(mmc35240_samp_freq)) return -EINVAL; - *val = mmc35240_samp_freq[i]; - *val2 = 0; - return IIO_VAL_INT; + *val = mmc35240_samp_freq[i].val; + *val2 = mmc35240_samp_freq[i].val2; + return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } @@ -496,6 +504,7 @@ static int mmc35240_probe(struct i2c_client *client, } data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); data->client = client; data->regmap = regmap; data->res = MMC35240_16_BITS_SLOW; diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index 2042e375f835..3d756bd8c703 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -80,6 +80,7 @@ #define SX9500_COMPSTAT_MASK GENMASK(3, 0) #define SX9500_NUM_CHANNELS 4 +#define SX9500_CHAN_MASK GENMASK(SX9500_NUM_CHANNELS - 1, 0) struct sx9500_data { struct mutex mutex; @@ -281,7 +282,7 @@ static int sx9500_read_prox_data(struct sx9500_data *data, if (ret < 0) return ret; - *val = 32767 - (s16)be16_to_cpu(regval); + *val = be16_to_cpu(regval); return IIO_VAL_INT; } @@ -329,27 +330,29 @@ static int sx9500_read_proximity(struct sx9500_data *data, else ret = sx9500_wait_for_sample(data); - if (ret < 0) - return ret; - mutex_lock(&data->mutex); - ret = sx9500_read_prox_data(data, chan, val); if (ret < 0) - goto out; + goto out_dec_data_rdy; - ret = sx9500_dec_chan_users(data, chan->channel); + ret = sx9500_read_prox_data(data, chan, val); if (ret < 0) - goto out; + goto out_dec_data_rdy; ret = sx9500_dec_data_rdy_users(data); if (ret < 0) + goto out_dec_chan; + + ret = sx9500_dec_chan_users(data, chan->channel); + if (ret < 0) goto out; ret = IIO_VAL_INT; goto out; +out_dec_data_rdy: + sx9500_dec_data_rdy_users(data); out_dec_chan: sx9500_dec_chan_users(data, chan->channel); out: @@ -679,7 +682,7 @@ out: static int sx9500_buffer_preenable(struct iio_dev *indio_dev) { struct sx9500_data *data = iio_priv(indio_dev); - int ret, i; + int ret = 0, i; mutex_lock(&data->mutex); @@ -703,7 +706,7 @@ static int sx9500_buffer_preenable(struct iio_dev *indio_dev) static int sx9500_buffer_predisable(struct iio_dev *indio_dev) { struct sx9500_data *data = iio_priv(indio_dev); - int ret, i; + int ret = 0, i; iio_triggered_buffer_predisable(indio_dev); @@ -800,8 +803,7 @@ static int sx9500_init_compensation(struct iio_dev *indio_dev) unsigned int val; ret = regmap_update_bits(data->regmap, SX9500_REG_PROX_CTRL0, - GENMASK(SX9500_NUM_CHANNELS, 0), - GENMASK(SX9500_NUM_CHANNELS, 0)); + SX9500_CHAN_MASK, SX9500_CHAN_MASK); if (ret < 0) return ret; @@ -821,7 +823,7 @@ static int sx9500_init_compensation(struct iio_dev *indio_dev) out: regmap_update_bits(data->regmap, SX9500_REG_PROX_CTRL0, - GENMASK(SX9500_NUM_CHANNELS, 0), 0); + SX9500_CHAN_MASK, 0); return ret; } diff --git a/drivers/iio/temperature/tmp006.c b/drivers/iio/temperature/tmp006.c index 395df23d7c8c..e78c1069a6a9 100644 --- a/drivers/iio/temperature/tmp006.c +++ b/drivers/iio/temperature/tmp006.c @@ -132,6 +132,9 @@ static int tmp006_write_raw(struct iio_dev *indio_dev, struct tmp006_data *data = iio_priv(indio_dev); int i; + if (mask != IIO_CHAN_INFO_SAMP_FREQ) + return -EINVAL; + for (i = 0; i < ARRAY_SIZE(tmp006_freqs); i++) if ((val == tmp006_freqs[i][0]) && (val2 == tmp006_freqs[i][1])) { diff --git a/drivers/infiniband/core/agent.c b/drivers/infiniband/core/agent.c index c7dcfe4ca5f1..0429040304fd 100644 --- a/drivers/infiniband/core/agent.c +++ b/drivers/infiniband/core/agent.c @@ -88,7 +88,7 @@ void agent_send_response(const struct ib_mad_hdr *mad_hdr, const struct ib_grh * struct ib_ah *ah; struct ib_mad_send_wr_private *mad_send_wr; - if (device->node_type == RDMA_NODE_IB_SWITCH) + if (rdma_cap_ib_switch(device)) port_priv = ib_get_agent_port(device, 0); else port_priv = ib_get_agent_port(device, port_num); @@ -122,7 +122,7 @@ void agent_send_response(const struct ib_mad_hdr *mad_hdr, const struct ib_grh * memcpy(send_buf->mad, mad_hdr, resp_mad_len); send_buf->ah = ah; - if (device->node_type == RDMA_NODE_IB_SWITCH) { + if (rdma_cap_ib_switch(device)) { mad_send_wr = container_of(send_buf, struct ib_mad_send_wr_private, send_buf); diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index dbddddd6fb5d..3a972ebf3c0d 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -169,6 +169,7 @@ struct cm_device { struct ib_device *ib_device; struct device *device; u8 ack_delay; + int going_down; struct cm_port *port[0]; }; @@ -805,6 +806,11 @@ static void cm_enter_timewait(struct cm_id_private *cm_id_priv) { int wait_time; unsigned long flags; + struct cm_device *cm_dev; + + cm_dev = ib_get_client_data(cm_id_priv->id.device, &cm_client); + if (!cm_dev) + return; spin_lock_irqsave(&cm.lock, flags); cm_cleanup_timewait(cm_id_priv->timewait_info); @@ -818,8 +824,14 @@ static void cm_enter_timewait(struct cm_id_private *cm_id_priv) */ cm_id_priv->id.state = IB_CM_TIMEWAIT; wait_time = cm_convert_to_ms(cm_id_priv->av.timeout); - queue_delayed_work(cm.wq, &cm_id_priv->timewait_info->work.work, - msecs_to_jiffies(wait_time)); + + /* Check if the device started its remove_one */ + spin_lock_irq(&cm.lock); + if (!cm_dev->going_down) + queue_delayed_work(cm.wq, &cm_id_priv->timewait_info->work.work, + msecs_to_jiffies(wait_time)); + spin_unlock_irq(&cm.lock); + cm_id_priv->timewait_info = NULL; } @@ -3305,6 +3317,11 @@ static int cm_establish(struct ib_cm_id *cm_id) struct cm_work *work; unsigned long flags; int ret = 0; + struct cm_device *cm_dev; + + cm_dev = ib_get_client_data(cm_id->device, &cm_client); + if (!cm_dev) + return -ENODEV; work = kmalloc(sizeof *work, GFP_ATOMIC); if (!work) @@ -3343,7 +3360,17 @@ static int cm_establish(struct ib_cm_id *cm_id) work->remote_id = cm_id->remote_id; work->mad_recv_wc = NULL; work->cm_event.event = IB_CM_USER_ESTABLISHED; - queue_delayed_work(cm.wq, &work->work, 0); + + /* Check if the device started its remove_one */ + spin_lock_irq(&cm.lock); + if (!cm_dev->going_down) { + queue_delayed_work(cm.wq, &work->work, 0); + } else { + kfree(work); + ret = -ENODEV; + } + spin_unlock_irq(&cm.lock); + out: return ret; } @@ -3394,6 +3421,7 @@ static void cm_recv_handler(struct ib_mad_agent *mad_agent, enum ib_cm_event_type event; u16 attr_id; int paths = 0; + int going_down = 0; switch (mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) { case CM_REQ_ATTR_ID: @@ -3452,7 +3480,19 @@ static void cm_recv_handler(struct ib_mad_agent *mad_agent, work->cm_event.event = event; work->mad_recv_wc = mad_recv_wc; work->port = port; - queue_delayed_work(cm.wq, &work->work, 0); + + /* Check if the device started its remove_one */ + spin_lock_irq(&cm.lock); + if (!port->cm_dev->going_down) + queue_delayed_work(cm.wq, &work->work, 0); + else + going_down = 1; + spin_unlock_irq(&cm.lock); + + if (going_down) { + kfree(work); + ib_free_recv_mad(mad_recv_wc); + } } static int cm_init_qp_init_attr(struct cm_id_private *cm_id_priv, @@ -3771,7 +3811,7 @@ static void cm_add_one(struct ib_device *ib_device) cm_dev->ib_device = ib_device; cm_get_ack_delay(cm_dev); - + cm_dev->going_down = 0; cm_dev->device = device_create(&cm_class, &ib_device->dev, MKDEV(0, 0), NULL, "%s", ib_device->name); @@ -3864,14 +3904,23 @@ static void cm_remove_one(struct ib_device *ib_device) list_del(&cm_dev->list); write_unlock_irqrestore(&cm.device_lock, flags); + spin_lock_irq(&cm.lock); + cm_dev->going_down = 1; + spin_unlock_irq(&cm.lock); + for (i = 1; i <= ib_device->phys_port_cnt; i++) { if (!rdma_cap_ib_cm(ib_device, i)) continue; port = cm_dev->port[i-1]; ib_modify_port(ib_device, port->port_num, 0, &port_modify); - ib_unregister_mad_agent(port->mad_agent); + /* + * We flush the queue here after the going_down set, this + * verify that no new works will be queued in the recv handler, + * after that we can call the unregister_mad_agent + */ flush_workqueue(cm.wq); + ib_unregister_mad_agent(port->mad_agent); cm_remove_port_fs(port); } device_unregister(cm_dev->device); diff --git a/drivers/infiniband/core/iwpm_msg.c b/drivers/infiniband/core/iwpm_msg.c index e6ffa2e66c1a..22a3abee2a54 100644 --- a/drivers/infiniband/core/iwpm_msg.c +++ b/drivers/infiniband/core/iwpm_msg.c @@ -67,7 +67,8 @@ int iwpm_register_pid(struct iwpm_dev_data *pm_msg, u8 nl_client) err_str = "Invalid port mapper client"; goto pid_query_error; } - if (iwpm_registered_client(nl_client)) + if (iwpm_check_registration(nl_client, IWPM_REG_VALID) || + iwpm_user_pid == IWPM_PID_UNAVAILABLE) return 0; skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REG_PID, &nlh, nl_client); if (!skb) { @@ -106,7 +107,6 @@ int iwpm_register_pid(struct iwpm_dev_data *pm_msg, u8 nl_client) ret = ibnl_multicast(skb, nlh, RDMA_NL_GROUP_IWPM, GFP_KERNEL); if (ret) { skb = NULL; /* skb is freed in the netlink send-op handling */ - iwpm_set_registered(nl_client, 1); iwpm_user_pid = IWPM_PID_UNAVAILABLE; err_str = "Unable to send a nlmsg"; goto pid_query_error; @@ -144,12 +144,12 @@ int iwpm_add_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client) err_str = "Invalid port mapper client"; goto add_mapping_error; } - if (!iwpm_registered_client(nl_client)) { + if (!iwpm_valid_pid()) + return 0; + if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) { err_str = "Unregistered port mapper client"; goto add_mapping_error; } - if (!iwpm_valid_pid()) - return 0; skb = iwpm_create_nlmsg(RDMA_NL_IWPM_ADD_MAPPING, &nlh, nl_client); if (!skb) { err_str = "Unable to create a nlmsg"; @@ -214,12 +214,12 @@ int iwpm_add_and_query_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client) err_str = "Invalid port mapper client"; goto query_mapping_error; } - if (!iwpm_registered_client(nl_client)) { + if (!iwpm_valid_pid()) + return 0; + if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) { err_str = "Unregistered port mapper client"; goto query_mapping_error; } - if (!iwpm_valid_pid()) - return 0; ret = -ENOMEM; skb = iwpm_create_nlmsg(RDMA_NL_IWPM_QUERY_MAPPING, &nlh, nl_client); if (!skb) { @@ -288,12 +288,12 @@ int iwpm_remove_mapping(struct sockaddr_storage *local_addr, u8 nl_client) err_str = "Invalid port mapper client"; goto remove_mapping_error; } - if (!iwpm_registered_client(nl_client)) { + if (!iwpm_valid_pid()) + return 0; + if (iwpm_check_registration(nl_client, IWPM_REG_UNDEF)) { err_str = "Unregistered port mapper client"; goto remove_mapping_error; } - if (!iwpm_valid_pid()) - return 0; skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REMOVE_MAPPING, &nlh, nl_client); if (!skb) { ret = -ENOMEM; @@ -388,7 +388,7 @@ int iwpm_register_pid_cb(struct sk_buff *skb, struct netlink_callback *cb) pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n", __func__, iwpm_user_pid); if (iwpm_valid_client(nl_client)) - iwpm_set_registered(nl_client, 1); + iwpm_set_registration(nl_client, IWPM_REG_VALID); register_pid_response_exit: nlmsg_request->request_done = 1; /* always for found nlmsg_request */ @@ -644,7 +644,6 @@ int iwpm_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb) { struct nlattr *nltb[IWPM_NLA_MAPINFO_REQ_MAX]; const char *msg_type = "Mapping Info response"; - int iwpm_pid; u8 nl_client; char *iwpm_name; u16 iwpm_version; @@ -669,14 +668,14 @@ int iwpm_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb) __func__, nl_client); return ret; } - iwpm_set_registered(nl_client, 0); + iwpm_set_registration(nl_client, IWPM_REG_INCOMPL); atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq); + iwpm_user_pid = cb->nlh->nlmsg_pid; if (!iwpm_mapinfo_available()) return 0; - iwpm_pid = cb->nlh->nlmsg_pid; pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n", - __func__, iwpm_pid); - ret = iwpm_send_mapinfo(nl_client, iwpm_pid); + __func__, iwpm_user_pid); + ret = iwpm_send_mapinfo(nl_client, iwpm_user_pid); return ret; } EXPORT_SYMBOL(iwpm_mapping_info_cb); diff --git a/drivers/infiniband/core/iwpm_util.c b/drivers/infiniband/core/iwpm_util.c index a626795bf9c7..5fb089e91353 100644 --- a/drivers/infiniband/core/iwpm_util.c +++ b/drivers/infiniband/core/iwpm_util.c @@ -78,6 +78,7 @@ init_exit: mutex_unlock(&iwpm_admin_lock); if (!ret) { iwpm_set_valid(nl_client, 1); + iwpm_set_registration(nl_client, IWPM_REG_UNDEF); pr_debug("%s: Mapinfo and reminfo tables are created\n", __func__); } @@ -106,6 +107,7 @@ int iwpm_exit(u8 nl_client) } mutex_unlock(&iwpm_admin_lock); iwpm_set_valid(nl_client, 0); + iwpm_set_registration(nl_client, IWPM_REG_UNDEF); return 0; } EXPORT_SYMBOL(iwpm_exit); @@ -397,17 +399,23 @@ void iwpm_set_valid(u8 nl_client, int valid) } /* valid client */ -int iwpm_registered_client(u8 nl_client) +u32 iwpm_get_registration(u8 nl_client) { return iwpm_admin.reg_list[nl_client]; } /* valid client */ -void iwpm_set_registered(u8 nl_client, int reg) +void iwpm_set_registration(u8 nl_client, u32 reg) { iwpm_admin.reg_list[nl_client] = reg; } +/* valid client */ +u32 iwpm_check_registration(u8 nl_client, u32 reg) +{ + return (iwpm_get_registration(nl_client) & reg); +} + int iwpm_compare_sockaddr(struct sockaddr_storage *a_sockaddr, struct sockaddr_storage *b_sockaddr) { diff --git a/drivers/infiniband/core/iwpm_util.h b/drivers/infiniband/core/iwpm_util.h index ee2d9ff095be..b7b9e194ce81 100644 --- a/drivers/infiniband/core/iwpm_util.h +++ b/drivers/infiniband/core/iwpm_util.h @@ -58,6 +58,10 @@ #define IWPM_PID_UNDEFINED -1 #define IWPM_PID_UNAVAILABLE -2 +#define IWPM_REG_UNDEF 0x01 +#define IWPM_REG_VALID 0x02 +#define IWPM_REG_INCOMPL 0x04 + struct iwpm_nlmsg_request { struct list_head inprocess_list; __u32 nlmsg_seq; @@ -88,7 +92,7 @@ struct iwpm_admin_data { atomic_t refcount; atomic_t nlmsg_seq; int client_list[RDMA_NL_NUM_CLIENTS]; - int reg_list[RDMA_NL_NUM_CLIENTS]; + u32 reg_list[RDMA_NL_NUM_CLIENTS]; }; /** @@ -159,19 +163,31 @@ int iwpm_valid_client(u8 nl_client); void iwpm_set_valid(u8 nl_client, int valid); /** - * iwpm_registered_client - Check if the port mapper client is registered + * iwpm_check_registration - Check if the client registration + * matches the given one * @nl_client: The index of the netlink client + * @reg: The given registration type to compare with * * Call iwpm_register_pid() to register a client + * Returns true if the client registration matches reg, + * otherwise returns false + */ +u32 iwpm_check_registration(u8 nl_client, u32 reg); + +/** + * iwpm_set_registration - Set the client registration + * @nl_client: The index of the netlink client + * @reg: Registration type to set */ -int iwpm_registered_client(u8 nl_client); +void iwpm_set_registration(u8 nl_client, u32 reg); /** - * iwpm_set_registered - Set the port mapper client to registered or not + * iwpm_get_registration * @nl_client: The index of the netlink client - * @reg: 1 if registered or 0 if not + * + * Returns the client registration type */ -void iwpm_set_registered(u8 nl_client, int reg); +u32 iwpm_get_registration(u8 nl_client); /** * iwpm_send_mapinfo - Send local and mapped IPv4/IPv6 address info of diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index a4b1466c1bf6..786fc51bf04b 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -769,7 +769,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv, bool opa = rdma_cap_opa_mad(mad_agent_priv->qp_info->port_priv->device, mad_agent_priv->qp_info->port_priv->port_num); - if (device->node_type == RDMA_NODE_IB_SWITCH && + if (rdma_cap_ib_switch(device) && smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) port_num = send_wr->wr.ud.port_num; else @@ -787,14 +787,15 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv, if ((opa_get_smp_direction(opa_smp) ? opa_smp->route.dr.dr_dlid : opa_smp->route.dr.dr_slid) == OPA_LID_PERMISSIVE && - opa_smi_handle_dr_smp_send(opa_smp, device->node_type, + opa_smi_handle_dr_smp_send(opa_smp, + rdma_cap_ib_switch(device), port_num) == IB_SMI_DISCARD) { ret = -EINVAL; dev_err(&device->dev, "OPA Invalid directed route\n"); goto out; } opa_drslid = be32_to_cpu(opa_smp->route.dr.dr_slid); - if (opa_drslid != OPA_LID_PERMISSIVE && + if (opa_drslid != be32_to_cpu(OPA_LID_PERMISSIVE) && opa_drslid & 0xffff0000) { ret = -EINVAL; dev_err(&device->dev, "OPA Invalid dr_slid 0x%x\n", @@ -810,7 +811,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv, } else { if ((ib_get_smp_direction(smp) ? smp->dr_dlid : smp->dr_slid) == IB_LID_PERMISSIVE && - smi_handle_dr_smp_send(smp, device->node_type, port_num) == + smi_handle_dr_smp_send(smp, rdma_cap_ib_switch(device), port_num) == IB_SMI_DISCARD) { ret = -EINVAL; dev_err(&device->dev, "Invalid directed route\n"); @@ -2030,7 +2031,7 @@ static enum smi_action handle_ib_smi(const struct ib_mad_port_private *port_priv struct ib_smp *smp = (struct ib_smp *)recv->mad; if (smi_handle_dr_smp_recv(smp, - port_priv->device->node_type, + rdma_cap_ib_switch(port_priv->device), port_num, port_priv->device->phys_port_cnt) == IB_SMI_DISCARD) @@ -2042,13 +2043,13 @@ static enum smi_action handle_ib_smi(const struct ib_mad_port_private *port_priv if (retsmi == IB_SMI_SEND) { /* don't forward */ if (smi_handle_dr_smp_send(smp, - port_priv->device->node_type, + rdma_cap_ib_switch(port_priv->device), port_num) == IB_SMI_DISCARD) return IB_SMI_DISCARD; if (smi_check_local_smp(smp, port_priv->device) == IB_SMI_DISCARD) return IB_SMI_DISCARD; - } else if (port_priv->device->node_type == RDMA_NODE_IB_SWITCH) { + } else if (rdma_cap_ib_switch(port_priv->device)) { /* forward case for switches */ memcpy(response, recv, mad_priv_size(response)); response->header.recv_wc.wc = &response->header.wc; @@ -2115,7 +2116,7 @@ handle_opa_smi(struct ib_mad_port_private *port_priv, struct opa_smp *smp = (struct opa_smp *)recv->mad; if (opa_smi_handle_dr_smp_recv(smp, - port_priv->device->node_type, + rdma_cap_ib_switch(port_priv->device), port_num, port_priv->device->phys_port_cnt) == IB_SMI_DISCARD) @@ -2127,7 +2128,7 @@ handle_opa_smi(struct ib_mad_port_private *port_priv, if (retsmi == IB_SMI_SEND) { /* don't forward */ if (opa_smi_handle_dr_smp_send(smp, - port_priv->device->node_type, + rdma_cap_ib_switch(port_priv->device), port_num) == IB_SMI_DISCARD) return IB_SMI_DISCARD; @@ -2135,7 +2136,7 @@ handle_opa_smi(struct ib_mad_port_private *port_priv, IB_SMI_DISCARD) return IB_SMI_DISCARD; - } else if (port_priv->device->node_type == RDMA_NODE_IB_SWITCH) { + } else if (rdma_cap_ib_switch(port_priv->device)) { /* forward case for switches */ memcpy(response, recv, mad_priv_size(response)); response->header.recv_wc.wc = &response->header.wc; @@ -2235,7 +2236,7 @@ static void ib_mad_recv_done_handler(struct ib_mad_port_private *port_priv, goto out; } - if (port_priv->device->node_type == RDMA_NODE_IB_SWITCH) + if (rdma_cap_ib_switch(port_priv->device)) port_num = wc->port_num; else port_num = port_priv->port_num; @@ -3297,17 +3298,11 @@ static int ib_mad_port_close(struct ib_device *device, int port_num) static void ib_mad_init_device(struct ib_device *device) { - int start, end, i; + int start, i; - if (device->node_type == RDMA_NODE_IB_SWITCH) { - start = 0; - end = 0; - } else { - start = 1; - end = device->phys_port_cnt; - } + start = rdma_start_port(device); - for (i = start; i <= end; i++) { + for (i = start; i <= rdma_end_port(device); i++) { if (!rdma_cap_ib_mad(device, i)) continue; @@ -3342,17 +3337,9 @@ error: static void ib_mad_remove_device(struct ib_device *device) { - int start, end, i; - - if (device->node_type == RDMA_NODE_IB_SWITCH) { - start = 0; - end = 0; - } else { - start = 1; - end = device->phys_port_cnt; - } + int i; - for (i = start; i <= end; i++) { + for (i = rdma_start_port(device); i <= rdma_end_port(device); i++) { if (!rdma_cap_ib_mad(device, i)) continue; diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c index 1244f02a5c6d..2cb865c7ce7a 100644 --- a/drivers/infiniband/core/multicast.c +++ b/drivers/infiniband/core/multicast.c @@ -812,12 +812,8 @@ static void mcast_add_one(struct ib_device *device) if (!dev) return; - if (device->node_type == RDMA_NODE_IB_SWITCH) - dev->start_port = dev->end_port = 0; - else { - dev->start_port = 1; - dev->end_port = device->phys_port_cnt; - } + dev->start_port = rdma_start_port(device); + dev->end_port = rdma_end_port(device); for (i = 0; i <= dev->end_port - dev->start_port; i++) { if (!rdma_cap_ib_mcast(device, dev->start_port + i)) diff --git a/drivers/infiniband/core/opa_smi.h b/drivers/infiniband/core/opa_smi.h index 62d91bfa4cb7..3bfab3505a29 100644 --- a/drivers/infiniband/core/opa_smi.h +++ b/drivers/infiniband/core/opa_smi.h @@ -39,12 +39,12 @@ #include "smi.h" -enum smi_action opa_smi_handle_dr_smp_recv(struct opa_smp *smp, u8 node_type, +enum smi_action opa_smi_handle_dr_smp_recv(struct opa_smp *smp, bool is_switch, int port_num, int phys_port_cnt); int opa_smi_get_fwd_port(struct opa_smp *smp); extern enum smi_forward_action opa_smi_check_forward_dr_smp(struct opa_smp *smp); extern enum smi_action opa_smi_handle_dr_smp_send(struct opa_smp *smp, - u8 node_type, int port_num); + bool is_switch, int port_num); /* * Return IB_SMI_HANDLE if the SMP should be handled by the local SMA/SM diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index 0fae85062a65..ca919f429666 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c @@ -1156,12 +1156,8 @@ static void ib_sa_add_one(struct ib_device *device) int s, e, i; int count = 0; - if (device->node_type == RDMA_NODE_IB_SWITCH) - s = e = 0; - else { - s = 1; - e = device->phys_port_cnt; - } + s = rdma_start_port(device); + e = rdma_end_port(device); sa_dev = kzalloc(sizeof *sa_dev + (e - s + 1) * sizeof (struct ib_sa_port), diff --git a/drivers/infiniband/core/smi.c b/drivers/infiniband/core/smi.c index 368a561d1a5d..f19b23817c2b 100644 --- a/drivers/infiniband/core/smi.c +++ b/drivers/infiniband/core/smi.c @@ -41,7 +41,7 @@ #include "smi.h" #include "opa_smi.h" -static enum smi_action __smi_handle_dr_smp_send(u8 node_type, int port_num, +static enum smi_action __smi_handle_dr_smp_send(bool is_switch, int port_num, u8 *hop_ptr, u8 hop_cnt, const u8 *initial_path, const u8 *return_path, @@ -64,7 +64,7 @@ static enum smi_action __smi_handle_dr_smp_send(u8 node_type, int port_num, /* C14-9:2 */ if (*hop_ptr && *hop_ptr < hop_cnt) { - if (node_type != RDMA_NODE_IB_SWITCH) + if (!is_switch) return IB_SMI_DISCARD; /* return_path set when received */ @@ -77,7 +77,7 @@ static enum smi_action __smi_handle_dr_smp_send(u8 node_type, int port_num, if (*hop_ptr == hop_cnt) { /* return_path set when received */ (*hop_ptr)++; - return (node_type == RDMA_NODE_IB_SWITCH || + return (is_switch || dr_dlid_is_permissive ? IB_SMI_HANDLE : IB_SMI_DISCARD); } @@ -96,7 +96,7 @@ static enum smi_action __smi_handle_dr_smp_send(u8 node_type, int port_num, /* C14-13:2 */ if (2 <= *hop_ptr && *hop_ptr <= hop_cnt) { - if (node_type != RDMA_NODE_IB_SWITCH) + if (!is_switch) return IB_SMI_DISCARD; (*hop_ptr)--; @@ -108,7 +108,7 @@ static enum smi_action __smi_handle_dr_smp_send(u8 node_type, int port_num, if (*hop_ptr == 1) { (*hop_ptr)--; /* C14-13:3 -- SMPs destined for SM shouldn't be here */ - return (node_type == RDMA_NODE_IB_SWITCH || + return (is_switch || dr_slid_is_permissive ? IB_SMI_HANDLE : IB_SMI_DISCARD); } @@ -127,9 +127,9 @@ static enum smi_action __smi_handle_dr_smp_send(u8 node_type, int port_num, * Return IB_SMI_DISCARD if the SMP should be discarded */ enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp, - u8 node_type, int port_num) + bool is_switch, int port_num) { - return __smi_handle_dr_smp_send(node_type, port_num, + return __smi_handle_dr_smp_send(is_switch, port_num, &smp->hop_ptr, smp->hop_cnt, smp->initial_path, smp->return_path, @@ -139,9 +139,9 @@ enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp, } enum smi_action opa_smi_handle_dr_smp_send(struct opa_smp *smp, - u8 node_type, int port_num) + bool is_switch, int port_num) { - return __smi_handle_dr_smp_send(node_type, port_num, + return __smi_handle_dr_smp_send(is_switch, port_num, &smp->hop_ptr, smp->hop_cnt, smp->route.dr.initial_path, smp->route.dr.return_path, @@ -152,7 +152,7 @@ enum smi_action opa_smi_handle_dr_smp_send(struct opa_smp *smp, OPA_LID_PERMISSIVE); } -static enum smi_action __smi_handle_dr_smp_recv(u8 node_type, int port_num, +static enum smi_action __smi_handle_dr_smp_recv(bool is_switch, int port_num, int phys_port_cnt, u8 *hop_ptr, u8 hop_cnt, const u8 *initial_path, @@ -173,7 +173,7 @@ static enum smi_action __smi_handle_dr_smp_recv(u8 node_type, int port_num, /* C14-9:2 -- intermediate hop */ if (*hop_ptr && *hop_ptr < hop_cnt) { - if (node_type != RDMA_NODE_IB_SWITCH) + if (!is_switch) return IB_SMI_DISCARD; return_path[*hop_ptr] = port_num; @@ -188,7 +188,7 @@ static enum smi_action __smi_handle_dr_smp_recv(u8 node_type, int port_num, return_path[*hop_ptr] = port_num; /* hop_ptr updated when sending */ - return (node_type == RDMA_NODE_IB_SWITCH || + return (is_switch || dr_dlid_is_permissive ? IB_SMI_HANDLE : IB_SMI_DISCARD); } @@ -208,7 +208,7 @@ static enum smi_action __smi_handle_dr_smp_recv(u8 node_type, int port_num, /* C14-13:2 */ if (2 <= *hop_ptr && *hop_ptr <= hop_cnt) { - if (node_type != RDMA_NODE_IB_SWITCH) + if (!is_switch) return IB_SMI_DISCARD; /* hop_ptr updated when sending */ @@ -224,8 +224,7 @@ static enum smi_action __smi_handle_dr_smp_recv(u8 node_type, int port_num, return IB_SMI_HANDLE; } /* hop_ptr updated when sending */ - return (node_type == RDMA_NODE_IB_SWITCH ? - IB_SMI_HANDLE : IB_SMI_DISCARD); + return (is_switch ? IB_SMI_HANDLE : IB_SMI_DISCARD); } /* C14-13:4 -- hop_ptr = 0 -> give to SM */ @@ -238,10 +237,10 @@ static enum smi_action __smi_handle_dr_smp_recv(u8 node_type, int port_num, * Adjust information for a received SMP * Return IB_SMI_DISCARD if the SMP should be dropped */ -enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type, +enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, bool is_switch, int port_num, int phys_port_cnt) { - return __smi_handle_dr_smp_recv(node_type, port_num, phys_port_cnt, + return __smi_handle_dr_smp_recv(is_switch, port_num, phys_port_cnt, &smp->hop_ptr, smp->hop_cnt, smp->initial_path, smp->return_path, @@ -254,10 +253,10 @@ enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type, * Adjust information for a received SMP * Return IB_SMI_DISCARD if the SMP should be dropped */ -enum smi_action opa_smi_handle_dr_smp_recv(struct opa_smp *smp, u8 node_type, +enum smi_action opa_smi_handle_dr_smp_recv(struct opa_smp *smp, bool is_switch, int port_num, int phys_port_cnt) { - return __smi_handle_dr_smp_recv(node_type, port_num, phys_port_cnt, + return __smi_handle_dr_smp_recv(is_switch, port_num, phys_port_cnt, &smp->hop_ptr, smp->hop_cnt, smp->route.dr.initial_path, smp->route.dr.return_path, diff --git a/drivers/infiniband/core/smi.h b/drivers/infiniband/core/smi.h index aff96bac49b4..33c91c8a16e9 100644 --- a/drivers/infiniband/core/smi.h +++ b/drivers/infiniband/core/smi.h @@ -51,12 +51,12 @@ enum smi_forward_action { IB_SMI_FORWARD /* SMP should be forwarded (for switches only) */ }; -enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type, +enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, bool is_switch, int port_num, int phys_port_cnt); int smi_get_fwd_port(struct ib_smp *smp); extern enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp); extern enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp, - u8 node_type, int port_num); + bool is_switch, int port_num); /* * Return IB_SMI_HANDLE if the SMP should be handled by the local SMA/SM diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index ed6b6c85c334..0b84a9cdfe5b 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c @@ -870,7 +870,7 @@ int ib_device_register_sysfs(struct ib_device *device, goto err_put; } - if (device->node_type == RDMA_NODE_IB_SWITCH) { + if (rdma_cap_ib_switch(device)) { ret = add_port(device, 0, port_callback); if (ret) goto err_put; diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index 62c24b1452b8..009481073644 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c @@ -1193,6 +1193,7 @@ static int ib_ucm_close(struct inode *inode, struct file *filp) return 0; } +static DECLARE_BITMAP(overflow_map, IB_UCM_MAX_DEVICES); static void ib_ucm_release_dev(struct device *dev) { struct ib_ucm_device *ucm_dev; @@ -1202,7 +1203,7 @@ static void ib_ucm_release_dev(struct device *dev) if (ucm_dev->devnum < IB_UCM_MAX_DEVICES) clear_bit(ucm_dev->devnum, dev_map); else - clear_bit(ucm_dev->devnum - IB_UCM_MAX_DEVICES, dev_map); + clear_bit(ucm_dev->devnum - IB_UCM_MAX_DEVICES, overflow_map); kfree(ucm_dev); } @@ -1226,7 +1227,6 @@ static ssize_t show_ibdev(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL); static dev_t overflow_maj; -static DECLARE_BITMAP(overflow_map, IB_UCM_MAX_DEVICES); static int find_overflow_devnum(void) { int ret; diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index ad45469f7582..29b21213ea75 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -1354,10 +1354,10 @@ static void ucma_lock_files(struct ucma_file *file1, struct ucma_file *file2) /* Acquire mutex's based on pointer comparison to prevent deadlock. */ if (file1 < file2) { mutex_lock(&file1->mut); - mutex_lock(&file2->mut); + mutex_lock_nested(&file2->mut, SINGLE_DEPTH_NESTING); } else { mutex_lock(&file2->mut); - mutex_lock(&file1->mut); + mutex_lock_nested(&file1->mut, SINGLE_DEPTH_NESTING); } } @@ -1616,6 +1616,7 @@ static void __exit ucma_cleanup(void) device_remove_file(ucma_misc.this_device, &dev_attr_abi_version); misc_deregister(&ucma_misc); idr_destroy(&ctx_idr); + idr_destroy(&multicast_idr); } module_init(ucma_init); diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c index b1b73232f217..bbbe0184e592 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_provider.c +++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c @@ -736,6 +736,10 @@ static struct ib_mr *iwch_get_dma_mr(struct ib_pd *pd, int acc) /* * T3 only supports 32 bits of size. */ + if (sizeof(phys_addr_t) > 4) { + pr_warn_once(MOD "Cannot support dma_mrs on this platform.\n"); + return ERR_PTR(-ENOTSUPP); + } bl.size = 0xffffffff; bl.addr = 0; kva = 0; diff --git a/drivers/infiniband/hw/ehca/ehca_sqp.c b/drivers/infiniband/hw/ehca/ehca_sqp.c index 12b5bc23832b..376b031c2c7f 100644 --- a/drivers/infiniband/hw/ehca/ehca_sqp.c +++ b/drivers/infiniband/hw/ehca/ehca_sqp.c @@ -226,8 +226,9 @@ int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, const struct ib_mad *in_mad = (const struct ib_mad *)in; struct ib_mad *out_mad = (struct ib_mad *)out; - BUG_ON(in_mad_size != sizeof(*in_mad) || - *out_mad_size != sizeof(*out_mad)); + if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) || + *out_mad_size != sizeof(*out_mad))) + return IB_MAD_RESULT_FAILURE; if (!port_num || port_num > ibdev->phys_port_cnt || !in_wc) return IB_MAD_RESULT_FAILURE; diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index 2d7e503d13cb..871dbe56216a 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c @@ -31,6 +31,8 @@ * SOFTWARE. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/sched.h> #include <linux/spinlock.h> #include <linux/idr.h> @@ -399,8 +401,8 @@ static int ipath_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) u32 bar0 = 0, bar1 = 0; #ifdef CONFIG_X86_64 - if (WARN(pat_enabled(), - "ipath needs PAT disabled, boot with nopat kernel parameter\n")) { + if (pat_enabled()) { + pr_warn("ipath needs PAT disabled, boot with nopat kernel parameter\n"); ret = -ENODEV; goto bail; } diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c index 948188e37f95..ad3a926ab3c5 100644 --- a/drivers/infiniband/hw/ipath/ipath_mad.c +++ b/drivers/infiniband/hw/ipath/ipath_mad.c @@ -1499,8 +1499,9 @@ int ipath_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, const struct ib_mad *in_mad = (const struct ib_mad *)in; struct ib_mad *out_mad = (struct ib_mad *)out; - BUG_ON(in_mad_size != sizeof(*in_mad) || - *out_mad_size != sizeof(*out_mad)); + if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) || + *out_mad_size != sizeof(*out_mad))) + return IB_MAD_RESULT_FAILURE; switch (in_mad->mad_hdr.mgmt_class) { case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE: diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c index 48253b839a6f..30ba49c4a98c 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/drivers/infiniband/hw/ipath/ipath_verbs.c @@ -2044,9 +2044,9 @@ int ipath_register_ib_device(struct ipath_devdata *dd) spin_lock_init(&idev->qp_table.lock); spin_lock_init(&idev->lk_table.lock); - idev->sm_lid = __constant_be16_to_cpu(IB_LID_PERMISSIVE); + idev->sm_lid = be16_to_cpu(IB_LID_PERMISSIVE); /* Set the prefix to the default value (see ch. 4.1.1) */ - idev->gid_prefix = __constant_cpu_to_be64(0xfe80000000000000ULL); + idev->gid_prefix = cpu_to_be64(0xfe80000000000000ULL); ret = ipath_init_qp_table(idev, ib_ipath_qp_table_size); if (ret) diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index 85a50df2f203..68b3dfa922bf 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c @@ -860,21 +860,31 @@ int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, struct mlx4_ib_dev *dev = to_mdev(ibdev); const struct ib_mad *in_mad = (const struct ib_mad *)in; struct ib_mad *out_mad = (struct ib_mad *)out; + enum rdma_link_layer link = rdma_port_get_link_layer(ibdev, port_num); - BUG_ON(in_mad_size != sizeof(*in_mad) || - *out_mad_size != sizeof(*out_mad)); + if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) || + *out_mad_size != sizeof(*out_mad))) + return IB_MAD_RESULT_FAILURE; - switch (rdma_port_get_link_layer(ibdev, port_num)) { - case IB_LINK_LAYER_INFINIBAND: - if (!mlx4_is_slave(dev->dev)) - return ib_process_mad(ibdev, mad_flags, port_num, in_wc, - in_grh, in_mad, out_mad); - case IB_LINK_LAYER_ETHERNET: - return iboe_process_mad(ibdev, mad_flags, port_num, in_wc, - in_grh, in_mad, out_mad); - default: - return -EINVAL; + /* iboe_process_mad() which uses the HCA flow-counters to implement IB PMA + * queries, should be called only by VFs and for that specific purpose + */ + if (link == IB_LINK_LAYER_INFINIBAND) { + if (mlx4_is_slave(dev->dev) && + in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT && + in_mad->mad_hdr.attr_id == IB_PMA_PORT_COUNTERS) + return iboe_process_mad(ibdev, mad_flags, port_num, in_wc, + in_grh, in_mad, out_mad); + + return ib_process_mad(ibdev, mad_flags, port_num, in_wc, + in_grh, in_mad, out_mad); } + + if (link == IB_LINK_LAYER_ETHERNET) + return iboe_process_mad(ibdev, mad_flags, port_num, in_wc, + in_grh, in_mad, out_mad); + + return -EINVAL; } static void send_handler(struct ib_mad_agent *agent, diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 067a691ecbed..8be6db816460 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -253,14 +253,15 @@ static int mlx4_ib_query_device(struct ib_device *ibdev, props->hca_core_clock = dev->dev->caps.hca_core_clock * 1000UL; props->timestamp_mask = 0xFFFFFFFFFFFFULL; - err = mlx4_get_internal_clock_params(dev->dev, &clock_params); - if (err) - goto out; + if (!mlx4_is_slave(dev->dev)) + err = mlx4_get_internal_clock_params(dev->dev, &clock_params); if (uhw->outlen >= resp.response_length + sizeof(resp.hca_core_clock_offset)) { - resp.hca_core_clock_offset = clock_params.offset % PAGE_SIZE; resp.response_length += sizeof(resp.hca_core_clock_offset); - resp.comp_mask |= QUERY_DEVICE_RESP_MASK_TIMESTAMP; + if (!err && !mlx4_is_slave(dev->dev)) { + resp.comp_mask |= QUERY_DEVICE_RESP_MASK_TIMESTAMP; + resp.hca_core_clock_offset = clock_params.offset % PAGE_SIZE; + } } if (uhw->outlen) { @@ -2669,31 +2670,33 @@ static void do_slave_init(struct mlx4_ib_dev *ibdev, int slave, int do_init) dm = kcalloc(ports, sizeof(*dm), GFP_ATOMIC); if (!dm) { pr_err("failed to allocate memory for tunneling qp update\n"); - goto out; + return; } for (i = 0; i < ports; i++) { dm[i] = kmalloc(sizeof (struct mlx4_ib_demux_work), GFP_ATOMIC); if (!dm[i]) { pr_err("failed to allocate memory for tunneling qp update work struct\n"); - for (i = 0; i < dev->caps.num_ports; i++) { - if (dm[i]) - kfree(dm[i]); - } + while (--i >= 0) + kfree(dm[i]); goto out; } - } - /* initialize or tear down tunnel QPs for the slave */ - for (i = 0; i < ports; i++) { INIT_WORK(&dm[i]->work, mlx4_ib_tunnels_update_work); dm[i]->port = first_port + i + 1; dm[i]->slave = slave; dm[i]->do_init = do_init; dm[i]->dev = ibdev; - spin_lock_irqsave(&ibdev->sriov.going_down_lock, flags); - if (!ibdev->sriov.is_going_down) + } + /* initialize or tear down tunnel QPs for the slave */ + spin_lock_irqsave(&ibdev->sriov.going_down_lock, flags); + if (!ibdev->sriov.is_going_down) { + for (i = 0; i < ports; i++) queue_work(ibdev->sriov.demux[i].ud_wq, &dm[i]->work); spin_unlock_irqrestore(&ibdev->sriov.going_down_lock, flags); + } else { + spin_unlock_irqrestore(&ibdev->sriov.going_down_lock, flags); + for (i = 0; i < ports; i++) + kfree(dm[i]); } out: kfree(dm); diff --git a/drivers/infiniband/hw/mlx5/mad.c b/drivers/infiniband/hw/mlx5/mad.c index 01fc97db45d6..b84d13a487cc 100644 --- a/drivers/infiniband/hw/mlx5/mad.c +++ b/drivers/infiniband/hw/mlx5/mad.c @@ -68,8 +68,9 @@ int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, const struct ib_mad *in_mad = (const struct ib_mad *)in; struct ib_mad *out_mad = (struct ib_mad *)out; - BUG_ON(in_mad_size != sizeof(*in_mad) || - *out_mad_size != sizeof(*out_mad)); + if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) || + *out_mad_size != sizeof(*out_mad))) + return IB_MAD_RESULT_FAILURE; slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE); diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c index 6b2418b74c99..7c3f2fb44ba5 100644 --- a/drivers/infiniband/hw/mthca/mthca_mad.c +++ b/drivers/infiniband/hw/mthca/mthca_mad.c @@ -209,8 +209,9 @@ int mthca_process_mad(struct ib_device *ibdev, const struct ib_mad *in_mad = (const struct ib_mad *)in; struct ib_mad *out_mad = (struct ib_mad *)out; - BUG_ON(in_mad_size != sizeof(*in_mad) || - *out_mad_size != sizeof(*out_mad)); + if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) || + *out_mad_size != sizeof(*out_mad))) + return IB_MAD_RESULT_FAILURE; /* Forward locally generated traps to the SM */ if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP && diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 9047af429906..8a3ad170d790 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -1520,8 +1520,9 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi int rc = arpindex; struct net_device *netdev; struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter; + __be32 dst_ipaddr = htonl(dst_ip); - rt = ip_route_output(&init_net, htonl(dst_ip), 0, 0, 0); + rt = ip_route_output(&init_net, dst_ipaddr, nesvnic->local_ipaddr, 0, 0); if (IS_ERR(rt)) { printk(KERN_ERR "%s: ip_route_output_key failed for 0x%08X\n", __func__, dst_ip); @@ -1533,7 +1534,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi else netdev = nesvnic->netdev; - neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, netdev); + neigh = dst_neigh_lookup(&rt->dst, &dst_ipaddr); rcu_read_lock(); if (neigh) { diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 02120d340d50..4713dd7ed764 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c @@ -3861,7 +3861,7 @@ void nes_manage_arp_cache(struct net_device *netdev, unsigned char *mac_addr, (((u32)mac_addr[2]) << 24) | (((u32)mac_addr[3]) << 16) | (((u32)mac_addr[4]) << 8) | (u32)mac_addr[5]); cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = cpu_to_le32( - (((u32)mac_addr[0]) << 16) | (u32)mac_addr[1]); + (((u32)mac_addr[0]) << 8) | (u32)mac_addr[1]); } else { cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX] = 0; cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = 0; diff --git a/drivers/infiniband/hw/ocrdma/ocrdma.h b/drivers/infiniband/hw/ocrdma/ocrdma.h index b396344fae16..6a36338593cd 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma.h @@ -1,21 +1,36 @@ -/******************************************************************* - * This file is part of the Emulex RoCE Device Driver for * - * RoCE (RDMA over Converged Ethernet) adapters. * - * Copyright (C) 2008-2012 Emulex. All rights reserved. * - * EMULEX and SLI are trademarks of Emulex. * - * www.emulex.com * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of version 2 of the GNU General * - * Public License as published by the Free Software Foundation. * - * This program is distributed in the hope that it will be useful. * - * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * - * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * - * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * - * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * - * TO BE LEGALLY INVALID. See the GNU General Public License for * - * more details, a copy of which can be found in the file COPYING * - * included with this package. * +/* This file is part of the Emulex RoCE Device Driver for + * RoCE (RDMA over Converged Ethernet) adapters. + * Copyright (C) 2012-2015 Emulex. All rights reserved. + * EMULEX and SLI are trademarks of Emulex. + * www.emulex.com + * + * This software is available to you under a choice of one of two licenses. + * You may choose to be licensed under the terms of the GNU General Public + * License (GPL) Version 2, available from the file COPYING in the main + * directory of this source tree, or the BSD license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Contact Information: * linux-drivers@emulex.com @@ -23,7 +38,7 @@ * Emulex * 3333 Susan Street * Costa Mesa, CA 92626 - *******************************************************************/ + */ #ifndef __OCRDMA_H__ #define __OCRDMA_H__ diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_abi.h b/drivers/infiniband/hw/ocrdma/ocrdma_abi.h index 1554cca5712a..430b1350fe96 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_abi.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma_abi.h @@ -1,21 +1,36 @@ -/******************************************************************* - * This file is part of the Emulex RoCE Device Driver for * - * RoCE (RDMA over Converged Ethernet) adapters. * - * Copyright (C) 2008-2012 Emulex. All rights reserved. * - * EMULEX and SLI are trademarks of Emulex. * - * www.emulex.com * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of version 2 of the GNU General * - * Public License as published by the Free Software Foundation. * - * This program is distributed in the hope that it will be useful. * - * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * - * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * - * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * - * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * - * TO BE LEGALLY INVALID. See the GNU General Public License for * - * more details, a copy of which can be found in the file COPYING * - * included with this package. * +/* This file is part of the Emulex RoCE Device Driver for + * RoCE (RDMA over Converged Ethernet) adapters. + * Copyright (C) 2012-2015 Emulex. All rights reserved. + * EMULEX and SLI are trademarks of Emulex. + * www.emulex.com + * + * This software is available to you under a choice of one of two licenses. + * You may choose to be licensed under the terms of the GNU General Public + * License (GPL) Version 2, available from the file COPYING in the main + * directory of this source tree, or the BSD license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Contact Information: * linux-drivers@emulex.com @@ -23,7 +38,7 @@ * Emulex * 3333 Susan Street * Costa Mesa, CA 92626 - *******************************************************************/ + */ #ifndef __OCRDMA_ABI_H__ #define __OCRDMA_ABI_H__ diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c index 4bafa15708d0..44766fee1f4e 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c @@ -1,21 +1,36 @@ -/******************************************************************* - * This file is part of the Emulex RoCE Device Driver for * - * RoCE (RDMA over Converged Ethernet) adapters. * - * Copyright (C) 2008-2012 Emulex. All rights reserved. * - * EMULEX and SLI are trademarks of Emulex. * - * www.emulex.com * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of version 2 of the GNU General * - * Public License as published by the Free Software Foundation. * - * This program is distributed in the hope that it will be useful. * - * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * - * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * - * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * - * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * - * TO BE LEGALLY INVALID. See the GNU General Public License for * - * more details, a copy of which can be found in the file COPYING * - * included with this package. * +/* This file is part of the Emulex RoCE Device Driver for + * RoCE (RDMA over Converged Ethernet) adapters. + * Copyright (C) 2012-2015 Emulex. All rights reserved. + * EMULEX and SLI are trademarks of Emulex. + * www.emulex.com + * + * This software is available to you under a choice of one of two licenses. + * You may choose to be licensed under the terms of the GNU General Public + * License (GPL) Version 2, available from the file COPYING in the main + * directory of this source tree, or the BSD license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Contact Information: * linux-drivers@emulex.com @@ -23,7 +38,7 @@ * Emulex * 3333 Susan Street * Costa Mesa, CA 92626 - *******************************************************************/ + */ #include <net/neighbour.h> #include <net/netevent.h> @@ -215,8 +230,9 @@ int ocrdma_process_mad(struct ib_device *ibdev, const struct ib_mad *in_mad = (const struct ib_mad *)in; struct ib_mad *out_mad = (struct ib_mad *)out; - BUG_ON(in_mad_size != sizeof(*in_mad) || - *out_mad_size != sizeof(*out_mad)); + if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) || + *out_mad_size != sizeof(*out_mad))) + return IB_MAD_RESULT_FAILURE; switch (in_mad->mad_hdr.mgmt_class) { case IB_MGMT_CLASS_PERF_MGMT: diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_ah.h b/drivers/infiniband/hw/ocrdma/ocrdma_ah.h index cf366fe03cb8..04a30ae67473 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_ah.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma_ah.h @@ -1,21 +1,36 @@ -/******************************************************************* - * This file is part of the Emulex RoCE Device Driver for * - * RoCE (RDMA over Converged Ethernet) adapters. * - * Copyright (C) 2008-2012 Emulex. All rights reserved. * - * EMULEX and SLI are trademarks of Emulex. * - * www.emulex.com * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of version 2 of the GNU General * - * Public License as published by the Free Software Foundation. * - * This program is distributed in the hope that it will be useful. * - * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * - * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * - * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * - * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * - * TO BE LEGALLY INVALID. See the GNU General Public License for * - * more details, a copy of which can be found in the file COPYING * - * included with this package. * +/* This file is part of the Emulex RoCE Device Driver for + * RoCE (RDMA over Converged Ethernet) adapters. + * Copyright (C) 2012-2015 Emulex. All rights reserved. + * EMULEX and SLI are trademarks of Emulex. + * www.emulex.com + * + * This software is available to you under a choice of one of two licenses. + * You may choose to be licensed under the terms of the GNU General Public + * License (GPL) Version 2, available from the file COPYING in the main + * directory of this source tree, or the BSD license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Contact Information: * linux-drivers@emulex.com @@ -23,7 +38,7 @@ * Emulex * 3333 Susan Street * Costa Mesa, CA 92626 - *******************************************************************/ + */ #ifndef __OCRDMA_AH_H__ #define __OCRDMA_AH_H__ diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c index 47615ff33bc6..aab391a15db4 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c @@ -1,21 +1,36 @@ -/******************************************************************* - * This file is part of the Emulex RoCE Device Driver for * - * RoCE (RDMA over Converged Ethernet) CNA Adapters. * - * Copyright (C) 2008-2012 Emulex. All rights reserved. * - * EMULEX and SLI are trademarks of Emulex. * - * www.emulex.com * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of version 2 of the GNU General * - * Public License as published by the Free Software Foundation. * - * This program is distributed in the hope that it will be useful. * - * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * - * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * - * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * - * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * - * TO BE LEGALLY INVALID. See the GNU General Public License for * - * more details, a copy of which can be found in the file COPYING * - * included with this package. * +/* This file is part of the Emulex RoCE Device Driver for + * RoCE (RDMA over Converged Ethernet) adapters. + * Copyright (C) 2012-2015 Emulex. All rights reserved. + * EMULEX and SLI are trademarks of Emulex. + * www.emulex.com + * + * This software is available to you under a choice of one of two licenses. + * You may choose to be licensed under the terms of the GNU General Public + * License (GPL) Version 2, available from the file COPYING in the main + * directory of this source tree, or the BSD license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Contact Information: * linux-drivers@emulex.com @@ -23,7 +38,7 @@ * Emulex * 3333 Susan Street * Costa Mesa, CA 92626 - *******************************************************************/ + */ #include <linux/sched.h> #include <linux/interrupt.h> diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.h b/drivers/infiniband/hw/ocrdma/ocrdma_hw.h index e905972fceb7..7ed885c1851e 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.h @@ -1,21 +1,36 @@ -/******************************************************************* - * This file is part of the Emulex RoCE Device Driver for * - * RoCE (RDMA over Converged Ethernet) CNA Adapters. * - * Copyright (C) 2008-2012 Emulex. All rights reserved. * - * EMULEX and SLI are trademarks of Emulex. * - * www.emulex.com * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of version 2 of the GNU General * - * Public License as published by the Free Software Foundation. * - * This program is distributed in the hope that it will be useful. * - * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * - * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * - * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * - * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * - * TO BE LEGALLY INVALID. See the GNU General Public License for * - * more details, a copy of which can be found in the file COPYING * - * included with this package. * +/* This file is part of the Emulex RoCE Device Driver for + * RoCE (RDMA over Converged Ethernet) adapters. + * Copyright (C) 2012-2015 Emulex. All rights reserved. + * EMULEX and SLI are trademarks of Emulex. + * www.emulex.com + * + * This software is available to you under a choice of one of two licenses. + * You may choose to be licensed under the terms of the GNU General Public + * License (GPL) Version 2, available from the file COPYING in the main + * directory of this source tree, or the BSD license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Contact Information: * linux-drivers@emulex.com @@ -23,7 +38,7 @@ * Emulex * 3333 Susan Street * Costa Mesa, CA 92626 - *******************************************************************/ + */ #ifndef __OCRDMA_HW_H__ #define __OCRDMA_HW_H__ diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c index 8a1398b253a2..b119a3413a15 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c @@ -1,21 +1,36 @@ -/******************************************************************* - * This file is part of the Emulex RoCE Device Driver for * - * RoCE (RDMA over Converged Ethernet) adapters. * - * Copyright (C) 2008-2012 Emulex. All rights reserved. * - * EMULEX and SLI are trademarks of Emulex. * - * www.emulex.com * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of version 2 of the GNU General * - * Public License as published by the Free Software Foundation. * - * This program is distributed in the hope that it will be useful. * - * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * - * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * - * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * - * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * - * TO BE LEGALLY INVALID. See the GNU General Public License for * - * more details, a copy of which can be found in the file COPYING * - * included with this package. * +/* This file is part of the Emulex RoCE Device Driver for + * RoCE (RDMA over Converged Ethernet) adapters. + * Copyright (C) 2012-2015 Emulex. All rights reserved. + * EMULEX and SLI are trademarks of Emulex. + * www.emulex.com + * + * This software is available to you under a choice of one of two licenses. + * You may choose to be licensed under the terms of the GNU General Public + * License (GPL) Version 2, available from the file COPYING in the main + * directory of this source tree, or the BSD license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Contact Information: * linux-drivers@emulex.com @@ -23,7 +38,7 @@ * Emulex * 3333 Susan Street * Costa Mesa, CA 92626 - *******************************************************************/ + */ #include <linux/module.h> #include <linux/idr.h> @@ -46,7 +61,7 @@ MODULE_VERSION(OCRDMA_ROCE_DRV_VERSION); MODULE_DESCRIPTION(OCRDMA_ROCE_DRV_DESC " " OCRDMA_ROCE_DRV_VERSION); MODULE_AUTHOR("Emulex Corporation"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("Dual BSD/GPL"); static LIST_HEAD(ocrdma_dev_list); static DEFINE_SPINLOCK(ocrdma_devlist_lock); @@ -696,6 +711,7 @@ static void __exit ocrdma_exit_module(void) ocrdma_unregister_inet6addr_notifier(); ocrdma_unregister_inetaddr_notifier(); ocrdma_rem_debugfs(); + idr_destroy(&ocrdma_dev_id); } module_init(ocrdma_init_module); diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_sli.h b/drivers/infiniband/hw/ocrdma/ocrdma_sli.h index 02ad0aee99af..80006b24aa11 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_sli.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma_sli.h @@ -1,21 +1,36 @@ -/******************************************************************* - * This file is part of the Emulex RoCE Device Driver for * - * RoCE (RDMA over Converged Ethernet) adapters. * - * Copyright (C) 2008-2012 Emulex. All rights reserved. * - * EMULEX and SLI are trademarks of Emulex. * - * www.emulex.com * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of version 2 of the GNU General * - * Public License as published by the Free Software Foundation. * - * This program is distributed in the hope that it will be useful. * - * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * - * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * - * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * - * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * - * TO BE LEGALLY INVALID. See the GNU General Public License for * - * more details, a copy of which can be found in the file COPYING * - * included with this package. * +/* This file is part of the Emulex RoCE Device Driver for + * RoCE (RDMA over Converged Ethernet) adapters. + * Copyright (C) 2012-2015 Emulex. All rights reserved. + * EMULEX and SLI are trademarks of Emulex. + * www.emulex.com + * + * This software is available to you under a choice of one of two licenses. + * You may choose to be licensed under the terms of the GNU General Public + * License (GPL) Version 2, available from the file COPYING in the main + * directory of this source tree, or the BSD license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Contact Information: * linux-drivers@emulex.com @@ -23,7 +38,7 @@ * Emulex * 3333 Susan Street * Costa Mesa, CA 92626 - *******************************************************************/ + */ #ifndef __OCRDMA_SLI_H__ #define __OCRDMA_SLI_H__ diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_stats.c b/drivers/infiniband/hw/ocrdma/ocrdma_stats.c index 48d7ef51aa0c..69334e214571 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_stats.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_stats.c @@ -1,21 +1,36 @@ -/******************************************************************* - * This file is part of the Emulex RoCE Device Driver for * - * RoCE (RDMA over Converged Ethernet) adapters. * - * Copyright (C) 2008-2014 Emulex. All rights reserved. * - * EMULEX and SLI are trademarks of Emulex. * - * www.emulex.com * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of version 2 of the GNU General * - * Public License as published by the Free Software Foundation. * - * This program is distributed in the hope that it will be useful. * - * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * - * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * - * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * - * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * - * TO BE LEGALLY INVALID. See the GNU General Public License for * - * more details, a copy of which can be found in the file COPYING * - * included with this package. * +/* This file is part of the Emulex RoCE Device Driver for + * RoCE (RDMA over Converged Ethernet) adapters. + * Copyright (C) 2012-2015 Emulex. All rights reserved. + * EMULEX and SLI are trademarks of Emulex. + * www.emulex.com + * + * This software is available to you under a choice of one of two licenses. + * You may choose to be licensed under the terms of the GNU General Public + * License (GPL) Version 2, available from the file COPYING in the main + * directory of this source tree, or the BSD license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Contact Information: * linux-drivers@emulex.com @@ -23,7 +38,7 @@ * Emulex * 3333 Susan Street * Costa Mesa, CA 92626 - *******************************************************************/ + */ #include <rdma/ib_addr.h> #include <rdma/ib_pma.h> diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_stats.h b/drivers/infiniband/hw/ocrdma/ocrdma_stats.h index 091edd68a8a3..c9e58d04c7b8 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_stats.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma_stats.h @@ -1,21 +1,36 @@ -/******************************************************************* - * This file is part of the Emulex RoCE Device Driver for * - * RoCE (RDMA over Converged Ethernet) adapters. * - * Copyright (C) 2008-2014 Emulex. All rights reserved. * - * EMULEX and SLI are trademarks of Emulex. * - * www.emulex.com * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of version 2 of the GNU General * - * Public License as published by the Free Software Foundation. * - * This program is distributed in the hope that it will be useful. * - * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * - * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * - * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * - * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * - * TO BE LEGALLY INVALID. See the GNU General Public License for * - * more details, a copy of which can be found in the file COPYING * - * included with this package. * +/* This file is part of the Emulex RoCE Device Driver for + * RoCE (RDMA over Converged Ethernet) adapters. + * Copyright (C) 2012-2015 Emulex. All rights reserved. + * EMULEX and SLI are trademarks of Emulex. + * www.emulex.com + * + * This software is available to you under a choice of one of two licenses. + * You may choose to be licensed under the terms of the GNU General Public + * License (GPL) Version 2, available from the file COPYING in the main + * directory of this source tree, or the BSD license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Contact Information: * linux-drivers@emulex.com @@ -23,7 +38,7 @@ * Emulex * 3333 Susan Street * Costa Mesa, CA 92626 - *******************************************************************/ + */ #ifndef __OCRDMA_STATS_H__ #define __OCRDMA_STATS_H__ diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index 5bb61eb58f2c..bc84cd462ecf 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -1,21 +1,36 @@ -/******************************************************************* - * This file is part of the Emulex RoCE Device Driver for * - * RoCE (RDMA over Converged Ethernet) adapters. * - * Copyright (C) 2008-2012 Emulex. All rights reserved. * - * EMULEX and SLI are trademarks of Emulex. * - * www.emulex.com * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of version 2 of the GNU General * - * Public License as published by the Free Software Foundation. * - * This program is distributed in the hope that it will be useful. * - * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * - * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * - * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * - * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * - * TO BE LEGALLY INVALID. See the GNU General Public License for * - * more details, a copy of which can be found in the file COPYING * - * included with this package. * +/* This file is part of the Emulex RoCE Device Driver for + * RoCE (RDMA over Converged Ethernet) adapters. + * Copyright (C) 2012-2015 Emulex. All rights reserved. + * EMULEX and SLI are trademarks of Emulex. + * www.emulex.com + * + * This software is available to you under a choice of one of two licenses. + * You may choose to be licensed under the terms of the GNU General Public + * License (GPL) Version 2, available from the file COPYING in the main + * directory of this source tree, or the BSD license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Contact Information: * linux-drivers@emulex.com @@ -23,7 +38,7 @@ * Emulex * 3333 Susan Street * Costa Mesa, CA 92626 - *******************************************************************/ + */ #include <linux/dma-mapping.h> #include <rdma/ib_verbs.h> diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h index b15c608efa7b..eaccb2d3cb9f 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h @@ -1,21 +1,36 @@ -/******************************************************************* - * This file is part of the Emulex RoCE Device Driver for * - * RoCE (RDMA over Converged Ethernet) adapters. * - * Copyright (C) 2008-2012 Emulex. All rights reserved. * - * EMULEX and SLI are trademarks of Emulex. * - * www.emulex.com * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of version 2 of the GNU General * - * Public License as published by the Free Software Foundation. * - * This program is distributed in the hope that it will be useful. * - * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * - * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * - * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * - * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * - * TO BE LEGALLY INVALID. See the GNU General Public License for * - * more details, a copy of which can be found in the file COPYING * - * included with this package. * +/* This file is part of the Emulex RoCE Device Driver for + * RoCE (RDMA over Converged Ethernet) adapters. + * Copyright (C) 2012-2015 Emulex. All rights reserved. + * EMULEX and SLI are trademarks of Emulex. + * www.emulex.com + * + * This software is available to you under a choice of one of two licenses. + * You may choose to be licensed under the terms of the GNU General Public + * License (GPL) Version 2, available from the file COPYING in the main + * directory of this source tree, or the BSD license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Contact Information: * linux-drivers@emulex.com @@ -23,7 +38,7 @@ * Emulex * 3333 Susan Street * Costa Mesa, CA 92626 - *******************************************************************/ + */ #ifndef __OCRDMA_VERBS_H__ #define __OCRDMA_VERBS_H__ diff --git a/drivers/infiniband/hw/qib/qib_mad.c b/drivers/infiniband/hw/qib/qib_mad.c index 05e3242d8442..9625e7c438e5 100644 --- a/drivers/infiniband/hw/qib/qib_mad.c +++ b/drivers/infiniband/hw/qib/qib_mad.c @@ -2412,8 +2412,9 @@ int qib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port, const struct ib_mad *in_mad = (const struct ib_mad *)in; struct ib_mad *out_mad = (struct ib_mad *)out; - BUG_ON(in_mad_size != sizeof(*in_mad) || - *out_mad_size != sizeof(*out_mad)); + if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) || + *out_mad_size != sizeof(*out_mad))) + return IB_MAD_RESULT_FAILURE; switch (in_mad->mad_hdr.mgmt_class) { case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE: diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index bd94b0a6e9e5..79859c4d43c9 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -239,7 +239,7 @@ struct ipoib_cm_tx { struct net_device *dev; struct ipoib_neigh *neigh; struct ipoib_path *path; - struct ipoib_cm_tx_buf *tx_ring; + struct ipoib_tx_buf *tx_ring; unsigned tx_head; unsigned tx_tail; unsigned long flags; @@ -504,6 +504,33 @@ int ipoib_mcast_stop_thread(struct net_device *dev); void ipoib_mcast_dev_down(struct net_device *dev); void ipoib_mcast_dev_flush(struct net_device *dev); +int ipoib_dma_map_tx(struct ib_device *ca, struct ipoib_tx_buf *tx_req); +void ipoib_dma_unmap_tx(struct ipoib_dev_priv *priv, + struct ipoib_tx_buf *tx_req); + +static inline void ipoib_build_sge(struct ipoib_dev_priv *priv, + struct ipoib_tx_buf *tx_req) +{ + int i, off; + struct sk_buff *skb = tx_req->skb; + skb_frag_t *frags = skb_shinfo(skb)->frags; + int nr_frags = skb_shinfo(skb)->nr_frags; + u64 *mapping = tx_req->mapping; + + if (skb_headlen(skb)) { + priv->tx_sge[0].addr = mapping[0]; + priv->tx_sge[0].length = skb_headlen(skb); + off = 1; + } else + off = 0; + + for (i = 0; i < nr_frags; ++i) { + priv->tx_sge[i + off].addr = mapping[i + off]; + priv->tx_sge[i + off].length = skb_frag_size(&frags[i]); + } + priv->tx_wr.num_sge = nr_frags + off; +} + #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG struct ipoib_mcast_iter *ipoib_mcast_iter_init(struct net_device *dev); int ipoib_mcast_iter_next(struct ipoib_mcast_iter *iter); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index cf32a778e7d0..ee39be6ccfb0 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -694,14 +694,12 @@ repost: static inline int post_send(struct ipoib_dev_priv *priv, struct ipoib_cm_tx *tx, unsigned int wr_id, - u64 addr, int len) + struct ipoib_tx_buf *tx_req) { struct ib_send_wr *bad_wr; - priv->tx_sge[0].addr = addr; - priv->tx_sge[0].length = len; + ipoib_build_sge(priv, tx_req); - priv->tx_wr.num_sge = 1; priv->tx_wr.wr_id = wr_id | IPOIB_OP_CM; return ib_post_send(tx->qp, &priv->tx_wr, &bad_wr); @@ -710,8 +708,7 @@ static inline int post_send(struct ipoib_dev_priv *priv, void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_tx *tx) { struct ipoib_dev_priv *priv = netdev_priv(dev); - struct ipoib_cm_tx_buf *tx_req; - u64 addr; + struct ipoib_tx_buf *tx_req; int rc; if (unlikely(skb->len > tx->mtu)) { @@ -735,24 +732,21 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_ */ tx_req = &tx->tx_ring[tx->tx_head & (ipoib_sendq_size - 1)]; tx_req->skb = skb; - addr = ib_dma_map_single(priv->ca, skb->data, skb->len, DMA_TO_DEVICE); - if (unlikely(ib_dma_mapping_error(priv->ca, addr))) { + + if (unlikely(ipoib_dma_map_tx(priv->ca, tx_req))) { ++dev->stats.tx_errors; dev_kfree_skb_any(skb); return; } - tx_req->mapping = addr; - skb_orphan(skb); skb_dst_drop(skb); - rc = post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1), - addr, skb->len); + rc = post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1), tx_req); if (unlikely(rc)) { ipoib_warn(priv, "post_send failed, error %d\n", rc); ++dev->stats.tx_errors; - ib_dma_unmap_single(priv->ca, addr, skb->len, DMA_TO_DEVICE); + ipoib_dma_unmap_tx(priv, tx_req); dev_kfree_skb_any(skb); } else { dev->trans_start = jiffies; @@ -777,7 +771,7 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_cm_tx *tx = wc->qp->qp_context; unsigned int wr_id = wc->wr_id & ~IPOIB_OP_CM; - struct ipoib_cm_tx_buf *tx_req; + struct ipoib_tx_buf *tx_req; unsigned long flags; ipoib_dbg_data(priv, "cm send completion: id %d, status: %d\n", @@ -791,7 +785,7 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) tx_req = &tx->tx_ring[wr_id]; - ib_dma_unmap_single(priv->ca, tx_req->mapping, tx_req->skb->len, DMA_TO_DEVICE); + ipoib_dma_unmap_tx(priv, tx_req); /* FIXME: is this right? Shouldn't we only increment on success? */ ++dev->stats.tx_packets; @@ -1036,6 +1030,9 @@ static struct ib_qp *ipoib_cm_create_tx_qp(struct net_device *dev, struct ipoib_ struct ib_qp *tx_qp; + if (dev->features & NETIF_F_SG) + attr.cap.max_send_sge = MAX_SKB_FRAGS + 1; + tx_qp = ib_create_qp(priv->pd, &attr); if (PTR_ERR(tx_qp) == -EINVAL) { ipoib_warn(priv, "can't use GFP_NOIO for QPs on device %s, using GFP_KERNEL\n", @@ -1170,7 +1167,7 @@ err_tx: static void ipoib_cm_tx_destroy(struct ipoib_cm_tx *p) { struct ipoib_dev_priv *priv = netdev_priv(p->dev); - struct ipoib_cm_tx_buf *tx_req; + struct ipoib_tx_buf *tx_req; unsigned long begin; ipoib_dbg(priv, "Destroy active connection 0x%x head 0x%x tail 0x%x\n", @@ -1197,8 +1194,7 @@ timeout: while ((int) p->tx_tail - (int) p->tx_head < 0) { tx_req = &p->tx_ring[p->tx_tail & (ipoib_sendq_size - 1)]; - ib_dma_unmap_single(priv->ca, tx_req->mapping, tx_req->skb->len, - DMA_TO_DEVICE); + ipoib_dma_unmap_tx(priv, tx_req); dev_kfree_skb_any(tx_req->skb); ++p->tx_tail; netif_tx_lock_bh(p->dev); @@ -1455,7 +1451,6 @@ static void ipoib_cm_stale_task(struct work_struct *work) spin_unlock_irq(&priv->lock); } - static ssize_t show_mode(struct device *d, struct device_attribute *attr, char *buf) { diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 63b92cbb29ad..d266667ca9b8 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -263,8 +263,7 @@ repost: "for buf %d\n", wr_id); } -static int ipoib_dma_map_tx(struct ib_device *ca, - struct ipoib_tx_buf *tx_req) +int ipoib_dma_map_tx(struct ib_device *ca, struct ipoib_tx_buf *tx_req) { struct sk_buff *skb = tx_req->skb; u64 *mapping = tx_req->mapping; @@ -305,8 +304,8 @@ partial_error: return -EIO; } -static void ipoib_dma_unmap_tx(struct ib_device *ca, - struct ipoib_tx_buf *tx_req) +void ipoib_dma_unmap_tx(struct ipoib_dev_priv *priv, + struct ipoib_tx_buf *tx_req) { struct sk_buff *skb = tx_req->skb; u64 *mapping = tx_req->mapping; @@ -314,7 +313,8 @@ static void ipoib_dma_unmap_tx(struct ib_device *ca, int off; if (skb_headlen(skb)) { - ib_dma_unmap_single(ca, mapping[0], skb_headlen(skb), DMA_TO_DEVICE); + ib_dma_unmap_single(priv->ca, mapping[0], skb_headlen(skb), + DMA_TO_DEVICE); off = 1; } else off = 0; @@ -322,8 +322,8 @@ static void ipoib_dma_unmap_tx(struct ib_device *ca, for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) { const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - ib_dma_unmap_page(ca, mapping[i + off], skb_frag_size(frag), - DMA_TO_DEVICE); + ib_dma_unmap_page(priv->ca, mapping[i + off], + skb_frag_size(frag), DMA_TO_DEVICE); } } @@ -389,7 +389,7 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) tx_req = &priv->tx_ring[wr_id]; - ipoib_dma_unmap_tx(priv->ca, tx_req); + ipoib_dma_unmap_tx(priv, tx_req); ++dev->stats.tx_packets; dev->stats.tx_bytes += tx_req->skb->len; @@ -514,24 +514,10 @@ static inline int post_send(struct ipoib_dev_priv *priv, void *head, int hlen) { struct ib_send_wr *bad_wr; - int i, off; struct sk_buff *skb = tx_req->skb; - skb_frag_t *frags = skb_shinfo(skb)->frags; - int nr_frags = skb_shinfo(skb)->nr_frags; - u64 *mapping = tx_req->mapping; - if (skb_headlen(skb)) { - priv->tx_sge[0].addr = mapping[0]; - priv->tx_sge[0].length = skb_headlen(skb); - off = 1; - } else - off = 0; + ipoib_build_sge(priv, tx_req); - for (i = 0; i < nr_frags; ++i) { - priv->tx_sge[i + off].addr = mapping[i + off]; - priv->tx_sge[i + off].length = skb_frag_size(&frags[i]); - } - priv->tx_wr.num_sge = nr_frags + off; priv->tx_wr.wr_id = wr_id; priv->tx_wr.wr.ud.remote_qpn = qpn; priv->tx_wr.wr.ud.ah = address; @@ -617,7 +603,7 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, ipoib_warn(priv, "post_send failed, error %d\n", rc); ++dev->stats.tx_errors; --priv->tx_outstanding; - ipoib_dma_unmap_tx(priv->ca, tx_req); + ipoib_dma_unmap_tx(priv, tx_req); dev_kfree_skb_any(skb); if (netif_queue_stopped(dev)) netif_wake_queue(dev); @@ -868,7 +854,7 @@ int ipoib_ib_dev_stop(struct net_device *dev) while ((int) priv->tx_tail - (int) priv->tx_head < 0) { tx_req = &priv->tx_ring[priv->tx_tail & (ipoib_sendq_size - 1)]; - ipoib_dma_unmap_tx(priv->ca, tx_req); + ipoib_dma_unmap_tx(priv, tx_req); dev_kfree_skb_any(tx_req->skb); ++priv->tx_tail; --priv->tx_outstanding; @@ -985,20 +971,21 @@ static inline int update_child_pkey(struct ipoib_dev_priv *priv) } static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, - enum ipoib_flush_level level) + enum ipoib_flush_level level, + int nesting) { struct ipoib_dev_priv *cpriv; struct net_device *dev = priv->dev; int result; - down_read(&priv->vlan_rwsem); + down_read_nested(&priv->vlan_rwsem, nesting); /* * Flush any child interfaces too -- they might be up even if * the parent is down. */ list_for_each_entry(cpriv, &priv->child_intfs, list) - __ipoib_ib_dev_flush(cpriv, level); + __ipoib_ib_dev_flush(cpriv, level, nesting + 1); up_read(&priv->vlan_rwsem); @@ -1076,7 +1063,7 @@ void ipoib_ib_dev_flush_light(struct work_struct *work) struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv, flush_light); - __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_LIGHT); + __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_LIGHT, 0); } void ipoib_ib_dev_flush_normal(struct work_struct *work) @@ -1084,7 +1071,7 @@ void ipoib_ib_dev_flush_normal(struct work_struct *work) struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv, flush_normal); - __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_NORMAL); + __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_NORMAL, 0); } void ipoib_ib_dev_flush_heavy(struct work_struct *work) @@ -1092,7 +1079,7 @@ void ipoib_ib_dev_flush_heavy(struct work_struct *work) struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv, flush_heavy); - __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_HEAVY); + __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_HEAVY, 0); } void ipoib_ib_dev_cleanup(struct net_device *dev) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index da149c278cb8..b2943c84a5dd 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -190,7 +190,7 @@ static netdev_features_t ipoib_fix_features(struct net_device *dev, netdev_featu struct ipoib_dev_priv *priv = netdev_priv(dev); if (test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags)) - features &= ~(NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); + features &= ~(NETIF_F_IP_CSUM | NETIF_F_TSO); return features; } @@ -232,6 +232,7 @@ int ipoib_set_mode(struct net_device *dev, const char *buf) ipoib_warn(priv, "enabling connected mode " "will cause multicast packet drops\n"); netdev_update_features(dev); + dev_set_mtu(dev, ipoib_cm_max_mtu(dev)); rtnl_unlock(); priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM; @@ -1577,7 +1578,8 @@ static struct net_device *ipoib_add_port(const char *format, SET_NETDEV_DEV(priv->dev, hca->dma_device); priv->dev->dev_id = port - 1; - if (!ib_query_port(hca, port, &attr)) + result = ib_query_port(hca, port, &attr); + if (!result) priv->max_ib_mtu = ib_mtu_enum_to_int(attr.max_mtu); else { printk(KERN_WARNING "%s: ib_query_port %d failed\n", @@ -1598,7 +1600,8 @@ static struct net_device *ipoib_add_port(const char *format, goto device_init_failed; } - if (ipoib_set_dev_features(priv, hca)) + result = ipoib_set_dev_features(priv, hca); + if (result) goto device_init_failed; /* @@ -1684,7 +1687,7 @@ static void ipoib_add_one(struct ib_device *device) struct list_head *dev_list; struct net_device *dev; struct ipoib_dev_priv *priv; - int s, e, p; + int p; int count = 0; dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL); @@ -1693,15 +1696,7 @@ static void ipoib_add_one(struct ib_device *device) INIT_LIST_HEAD(dev_list); - if (device->node_type == RDMA_NODE_IB_SWITCH) { - s = 0; - e = 0; - } else { - s = 1; - e = device->phys_port_cnt; - } - - for (p = s; p <= e; ++p) { + for (p = rdma_start_port(device); p <= rdma_end_port(device); ++p) { if (!rdma_protocol_ib(device, p)) continue; dev = ipoib_add_port("ib%d", device, p); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c index 9e6ee82a8fd7..851c8219d501 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c @@ -177,7 +177,8 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca) else size += ipoib_recvq_size * ipoib_max_conn_qp; } else - goto out_free_wq; + if (ret != -ENOSYS) + goto out_free_wq; cq_attr.cqe = size; priv->recv_cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 771700963127..d851e1828d6f 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -775,6 +775,17 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) ret = isert_rdma_post_recvl(isert_conn); if (ret) goto out_conn_dev; + /* + * Obtain the second reference now before isert_rdma_accept() to + * ensure that any initiator generated REJECT CM event that occurs + * asynchronously won't drop the last reference until the error path + * in iscsi_target_login_sess_out() does it's ->iscsit_free_conn() -> + * isert_free_conn() -> isert_put_conn() -> kref_put(). + */ + if (!kref_get_unless_zero(&isert_conn->kref)) { + isert_warn("conn %p connect_release is running\n", isert_conn); + goto out_conn_dev; + } ret = isert_rdma_accept(isert_conn); if (ret) @@ -836,11 +847,6 @@ isert_connected_handler(struct rdma_cm_id *cma_id) isert_info("conn %p\n", isert_conn); - if (!kref_get_unless_zero(&isert_conn->kref)) { - isert_warn("conn %p connect_release is running\n", isert_conn); - return; - } - mutex_lock(&isert_conn->mutex); if (isert_conn->state != ISER_CONN_FULL_FEATURE) isert_conn->state = ISER_CONN_UP; diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 267dc4f75502..31a20b462266 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -161,13 +161,10 @@ static int srp_tmo_set(const char *val, const struct kernel_param *kp) { int tmo, res; - if (strncmp(val, "off", 3) != 0) { - res = kstrtoint(val, 0, &tmo); - if (res) - goto out; - } else { - tmo = -1; - } + res = srp_parse_tmo(&tmo, val); + if (res) + goto out; + if (kp->arg == &srp_reconnect_delay) res = srp_tmo_valid(tmo, srp_fast_io_fail_tmo, srp_dev_loss_tmo); @@ -3379,7 +3376,7 @@ static void srp_add_one(struct ib_device *device) struct srp_device *srp_dev; struct ib_device_attr *dev_attr; struct srp_host *host; - int mr_page_shift, s, e, p; + int mr_page_shift, p; u64 max_pages_per_mr; dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL); @@ -3443,15 +3440,7 @@ static void srp_add_one(struct ib_device *device) if (IS_ERR(srp_dev->mr)) goto err_pd; - if (device->node_type == RDMA_NODE_IB_SWITCH) { - s = 0; - e = 0; - } else { - s = 1; - e = device->phys_port_cnt; - } - - for (p = s; p <= e; ++p) { + for (p = rdma_start_port(device); p <= rdma_end_port(device); ++p) { host = srp_add_port(srp_dev, p); if (host) list_add_tail(&host->list, &srp_dev->dev_list); diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 82897ca17f32..60ff0a2390e5 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -302,7 +302,7 @@ static void srpt_get_iou(struct ib_dm_mad *mad) int i; ioui = (struct ib_dm_iou_info *)mad->data; - ioui->change_id = __constant_cpu_to_be16(1); + ioui->change_id = cpu_to_be16(1); ioui->max_controllers = 16; /* set present for slot 1 and empty for the rest */ @@ -330,13 +330,13 @@ static void srpt_get_ioc(struct srpt_port *sport, u32 slot, if (!slot || slot > 16) { mad->mad_hdr.status - = __constant_cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD); + = cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD); return; } if (slot > 2) { mad->mad_hdr.status - = __constant_cpu_to_be16(DM_MAD_STATUS_NO_IOC); + = cpu_to_be16(DM_MAD_STATUS_NO_IOC); return; } @@ -348,10 +348,10 @@ static void srpt_get_ioc(struct srpt_port *sport, u32 slot, iocp->device_version = cpu_to_be16(sdev->dev_attr.hw_ver); iocp->subsys_vendor_id = cpu_to_be32(sdev->dev_attr.vendor_id); iocp->subsys_device_id = 0x0; - iocp->io_class = __constant_cpu_to_be16(SRP_REV16A_IB_IO_CLASS); - iocp->io_subclass = __constant_cpu_to_be16(SRP_IO_SUBCLASS); - iocp->protocol = __constant_cpu_to_be16(SRP_PROTOCOL); - iocp->protocol_version = __constant_cpu_to_be16(SRP_PROTOCOL_VERSION); + iocp->io_class = cpu_to_be16(SRP_REV16A_IB_IO_CLASS); + iocp->io_subclass = cpu_to_be16(SRP_IO_SUBCLASS); + iocp->protocol = cpu_to_be16(SRP_PROTOCOL); + iocp->protocol_version = cpu_to_be16(SRP_PROTOCOL_VERSION); iocp->send_queue_depth = cpu_to_be16(sdev->srq_size); iocp->rdma_read_depth = 4; iocp->send_size = cpu_to_be32(srp_max_req_size); @@ -379,13 +379,13 @@ static void srpt_get_svc_entries(u64 ioc_guid, if (!slot || slot > 16) { mad->mad_hdr.status - = __constant_cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD); + = cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD); return; } if (slot > 2 || lo > hi || hi > 1) { mad->mad_hdr.status - = __constant_cpu_to_be16(DM_MAD_STATUS_NO_IOC); + = cpu_to_be16(DM_MAD_STATUS_NO_IOC); return; } @@ -436,7 +436,7 @@ static void srpt_mgmt_method_get(struct srpt_port *sp, struct ib_mad *rq_mad, break; default: rsp_mad->mad_hdr.status = - __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR); + cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR); break; } } @@ -493,11 +493,11 @@ static void srpt_mad_recv_handler(struct ib_mad_agent *mad_agent, break; case IB_MGMT_METHOD_SET: dm_mad->mad_hdr.status = - __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR); + cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR); break; default: dm_mad->mad_hdr.status = - __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD); + cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD); break; } @@ -1535,7 +1535,7 @@ static int srpt_build_cmd_rsp(struct srpt_rdma_ch *ch, memset(srp_rsp, 0, sizeof *srp_rsp); srp_rsp->opcode = SRP_RSP; srp_rsp->req_lim_delta = - __constant_cpu_to_be32(1 + atomic_xchg(&ch->req_lim_delta, 0)); + cpu_to_be32(1 + atomic_xchg(&ch->req_lim_delta, 0)); srp_rsp->tag = tag; srp_rsp->status = status; @@ -1585,8 +1585,8 @@ static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch, memset(srp_rsp, 0, sizeof *srp_rsp); srp_rsp->opcode = SRP_RSP; - srp_rsp->req_lim_delta = __constant_cpu_to_be32(1 - + atomic_xchg(&ch->req_lim_delta, 0)); + srp_rsp->req_lim_delta = + cpu_to_be32(1 + atomic_xchg(&ch->req_lim_delta, 0)); srp_rsp->tag = tag; srp_rsp->flags |= SRP_RSP_FLAG_RSPVALID; @@ -1630,7 +1630,7 @@ static uint64_t srpt_unpack_lun(const uint8_t *lun, int len) switch (len) { case 8: if ((*((__be64 *)lun) & - __constant_cpu_to_be64(0x0000FFFFFFFFFFFFLL)) != 0) + cpu_to_be64(0x0000FFFFFFFFFFFFLL)) != 0) goto out_err; break; case 4: @@ -2449,8 +2449,8 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, } if (it_iu_len > srp_max_req_size || it_iu_len < 64) { - rej->reason = __constant_cpu_to_be32( - SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE); + rej->reason = cpu_to_be32( + SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE); ret = -EINVAL; pr_err("rejected SRP_LOGIN_REQ because its" " length (%d bytes) is out of range (%d .. %d)\n", @@ -2459,8 +2459,8 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, } if (!sport->enabled) { - rej->reason = __constant_cpu_to_be32( - SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); + rej->reason = cpu_to_be32( + SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); ret = -EINVAL; pr_err("rejected SRP_LOGIN_REQ because the target port" " has not yet been enabled\n"); @@ -2505,8 +2505,8 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, if (*(__be64 *)req->target_port_id != cpu_to_be64(srpt_service_guid) || *(__be64 *)(req->target_port_id + 8) != cpu_to_be64(srpt_service_guid)) { - rej->reason = __constant_cpu_to_be32( - SRP_LOGIN_REJ_UNABLE_ASSOCIATE_CHANNEL); + rej->reason = cpu_to_be32( + SRP_LOGIN_REJ_UNABLE_ASSOCIATE_CHANNEL); ret = -ENOMEM; pr_err("rejected SRP_LOGIN_REQ because it" " has an invalid target port identifier.\n"); @@ -2515,8 +2515,8 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, ch = kzalloc(sizeof *ch, GFP_KERNEL); if (!ch) { - rej->reason = __constant_cpu_to_be32( - SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); + rej->reason = cpu_to_be32( + SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); pr_err("rejected SRP_LOGIN_REQ because no memory.\n"); ret = -ENOMEM; goto reject; @@ -2552,8 +2552,8 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, ret = srpt_create_ch_ib(ch); if (ret) { - rej->reason = __constant_cpu_to_be32( - SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); + rej->reason = cpu_to_be32( + SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); pr_err("rejected SRP_LOGIN_REQ because creating" " a new RDMA channel failed.\n"); goto free_ring; @@ -2561,8 +2561,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, ret = srpt_ch_qp_rtr(ch, ch->qp); if (ret) { - rej->reason = __constant_cpu_to_be32( - SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); + rej->reason = cpu_to_be32(SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); pr_err("rejected SRP_LOGIN_REQ because enabling" " RTR failed (error code = %d)\n", ret); goto destroy_ib; @@ -2580,15 +2579,15 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, if (!nacl) { pr_info("Rejected login because no ACL has been" " configured yet for initiator %s.\n", ch->sess_name); - rej->reason = __constant_cpu_to_be32( - SRP_LOGIN_REJ_CHANNEL_LIMIT_REACHED); + rej->reason = cpu_to_be32( + SRP_LOGIN_REJ_CHANNEL_LIMIT_REACHED); goto destroy_ib; } ch->sess = transport_init_session(TARGET_PROT_NORMAL); if (IS_ERR(ch->sess)) { - rej->reason = __constant_cpu_to_be32( - SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); + rej->reason = cpu_to_be32( + SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); pr_debug("Failed to create session\n"); goto deregister_session; } @@ -2604,8 +2603,8 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, rsp->max_it_iu_len = req->req_it_iu_len; rsp->max_ti_iu_len = req->req_it_iu_len; ch->max_ti_iu_len = it_iu_len; - rsp->buf_fmt = __constant_cpu_to_be16(SRP_BUF_FORMAT_DIRECT - | SRP_BUF_FORMAT_INDIRECT); + rsp->buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT + | SRP_BUF_FORMAT_INDIRECT); rsp->req_lim_delta = cpu_to_be32(ch->rq_size); atomic_set(&ch->req_lim, ch->rq_size); atomic_set(&ch->req_lim_delta, 0); @@ -2655,8 +2654,8 @@ free_ch: reject: rej->opcode = SRP_LOGIN_REJ; rej->tag = req->tag; - rej->buf_fmt = __constant_cpu_to_be16(SRP_BUF_FORMAT_DIRECT - | SRP_BUF_FORMAT_INDIRECT); + rej->buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT + | SRP_BUF_FORMAT_INDIRECT); ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED, NULL, 0, (void *)rej, sizeof *rej); diff --git a/drivers/input/input-leds.c b/drivers/input/input-leds.c index 074a65ed17bb..766bf2660116 100644 --- a/drivers/input/input-leds.c +++ b/drivers/input/input-leds.c @@ -71,6 +71,18 @@ static void input_leds_event(struct input_handle *handle, unsigned int type, { } +static int input_leds_get_count(struct input_dev *dev) +{ + unsigned int led_code; + int count = 0; + + for_each_set_bit(led_code, dev->ledbit, LED_CNT) + if (input_led_info[led_code].name) + count++; + + return count; +} + static int input_leds_connect(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id) @@ -81,7 +93,7 @@ static int input_leds_connect(struct input_handler *handler, int led_no; int error; - num_leds = bitmap_weight(dev->ledbit, LED_CNT); + num_leds = input_leds_get_count(dev); if (!num_leds) return -ENXIO; @@ -112,7 +124,7 @@ static int input_leds_connect(struct input_handler *handler, led->handle = &leds->handle; led->code = led_code; - if (WARN_ON(!input_led_info[led_code].name)) + if (!input_led_info[led_code].name) continue; led->cdev.name = kasprintf(GFP_KERNEL, "%s::%s", diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index 27b6a3ce18ca..891797ad76bc 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c @@ -196,7 +196,7 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs) if (n_buttons[i] < 1) continue; - if (n_buttons[i] > 6) { + if (n_buttons[i] > ARRAY_SIZE(tgfx_buttons)) { printk(KERN_ERR "turbografx.c: Invalid number of buttons %d\n", n_buttons[i]); err = -EINVAL; goto err_unreg_devs; diff --git a/drivers/input/misc/axp20x-pek.c b/drivers/input/misc/axp20x-pek.c index 10e140af5aac..1ac898db303a 100644 --- a/drivers/input/misc/axp20x-pek.c +++ b/drivers/input/misc/axp20x-pek.c @@ -292,3 +292,4 @@ module_platform_driver(axp20x_pek_driver); MODULE_DESCRIPTION("axp20x Power Button"); MODULE_AUTHOR("Carlo Caione <carlo@caione.org>"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:axp20x-pek"); diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c index fc17b9592f54..10c4e3d462f1 100644 --- a/drivers/input/misc/twl4030-vibra.c +++ b/drivers/input/misc/twl4030-vibra.c @@ -183,7 +183,8 @@ static bool twl4030_vibra_check_coexist(struct twl4030_vibra_data *pdata, if (pdata && pdata->coexist) return true; - if (of_find_node_by_name(node, "codec")) { + node = of_find_node_by_name(node, "codec"); + if (node) { of_node_put(node); return true; } diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 113d6f1516a5..4d246861d692 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -20,6 +20,7 @@ #include <linux/input/mt.h> #include <linux/serio.h> #include <linux/libps2.h> +#include <linux/dmi.h> #include "psmouse.h" #include "alps.h" @@ -99,6 +100,7 @@ static const struct alps_nibble_commands alps_v6_nibble_commands[] = { #define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */ #define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with 6-byte ALPS packet */ +#define ALPS_DELL 0x100 /* device is a Dell laptop */ #define ALPS_BUTTONPAD 0x200 /* device is a clickpad */ static const struct alps_model_info alps_model_data[] = { @@ -251,9 +253,9 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) return; } - /* Non interleaved V2 dualpoint has separate stick button bits */ + /* Dell non interleaved V2 dualpoint has separate stick button bits */ if (priv->proto_version == ALPS_PROTO_V2 && - priv->flags == (ALPS_PASS | ALPS_DUALPOINT)) { + priv->flags == (ALPS_DELL | ALPS_PASS | ALPS_DUALPOINT)) { left |= packet[0] & 1; right |= packet[0] & 2; middle |= packet[0] & 4; @@ -2550,6 +2552,8 @@ static int alps_set_protocol(struct psmouse *psmouse, priv->byte0 = protocol->byte0; priv->mask0 = protocol->mask0; priv->flags = protocol->flags; + if (dmi_name_in_vendors("Dell")) + priv->flags |= ALPS_DELL; priv->x_max = 2000; priv->y_max = 1400; diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index b10709f04615..30e3442518f8 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -2,6 +2,7 @@ * Apple USB BCM5974 (Macbook Air and Penryn Macbook Pro) multitouch driver * * Copyright (C) 2008 Henrik Rydberg (rydberg@euromail.se) + * Copyright (C) 2015 John Horan (knasher@gmail.com) * * The USB initialization and package decoding was made by * Scott Shawcroft as part of the touchd user-space driver project: @@ -91,6 +92,10 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI 0x0290 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO 0x0291 #define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS 0x0292 +/* MacbookPro12,1 (2015) */ +#define USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI 0x0272 +#define USB_DEVICE_ID_APPLE_WELLSPRING9_ISO 0x0273 +#define USB_DEVICE_ID_APPLE_WELLSPRING9_JIS 0x0274 #define BCM5974_DEVICE(prod) { \ .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ @@ -152,6 +157,10 @@ static const struct usb_device_id bcm5974_table[] = { BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING8_ISO), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING8_JIS), + /* MacbookPro12,1 */ + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING9_ISO), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING9_JIS), /* Terminating entry */ {} }; @@ -180,21 +189,47 @@ struct bt_data { enum tp_type { TYPE1, /* plain trackpad */ TYPE2, /* button integrated in trackpad */ - TYPE3 /* additional header fields since June 2013 */ + TYPE3, /* additional header fields since June 2013 */ + TYPE4 /* additional header field for pressure data */ }; /* trackpad finger data offsets, le16-aligned */ -#define FINGER_TYPE1 (13 * sizeof(__le16)) -#define FINGER_TYPE2 (15 * sizeof(__le16)) -#define FINGER_TYPE3 (19 * sizeof(__le16)) +#define HEADER_TYPE1 (13 * sizeof(__le16)) +#define HEADER_TYPE2 (15 * sizeof(__le16)) +#define HEADER_TYPE3 (19 * sizeof(__le16)) +#define HEADER_TYPE4 (23 * sizeof(__le16)) /* trackpad button data offsets */ +#define BUTTON_TYPE1 0 #define BUTTON_TYPE2 15 #define BUTTON_TYPE3 23 +#define BUTTON_TYPE4 31 /* list of device capability bits */ #define HAS_INTEGRATED_BUTTON 1 +/* trackpad finger data block size */ +#define FSIZE_TYPE1 (14 * sizeof(__le16)) +#define FSIZE_TYPE2 (14 * sizeof(__le16)) +#define FSIZE_TYPE3 (14 * sizeof(__le16)) +#define FSIZE_TYPE4 (15 * sizeof(__le16)) + +/* offset from header to finger struct */ +#define DELTA_TYPE1 (0 * sizeof(__le16)) +#define DELTA_TYPE2 (0 * sizeof(__le16)) +#define DELTA_TYPE3 (0 * sizeof(__le16)) +#define DELTA_TYPE4 (1 * sizeof(__le16)) + +/* usb control message mode switch data */ +#define USBMSG_TYPE1 8, 0x300, 0, 0, 0x1, 0x8 +#define USBMSG_TYPE2 8, 0x300, 0, 0, 0x1, 0x8 +#define USBMSG_TYPE3 8, 0x300, 0, 0, 0x1, 0x8 +#define USBMSG_TYPE4 2, 0x302, 2, 1, 0x1, 0x0 + +/* Wellspring initialization constants */ +#define BCM5974_WELLSPRING_MODE_READ_REQUEST_ID 1 +#define BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID 9 + /* trackpad finger structure, le16-aligned */ struct tp_finger { __le16 origin; /* zero when switching track finger */ @@ -207,14 +242,13 @@ struct tp_finger { __le16 orientation; /* 16384 when point, else 15 bit angle */ __le16 touch_major; /* touch area, major axis */ __le16 touch_minor; /* touch area, minor axis */ - __le16 unused[3]; /* zeros */ + __le16 unused[2]; /* zeros */ + __le16 pressure; /* pressure on forcetouch touchpad */ __le16 multi; /* one finger: varies, more fingers: constant */ } __attribute__((packed,aligned(2))); /* trackpad finger data size, empirically at least ten fingers */ #define MAX_FINGERS 16 -#define SIZEOF_FINGER sizeof(struct tp_finger) -#define SIZEOF_ALL_FINGERS (MAX_FINGERS * SIZEOF_FINGER) #define MAX_FINGER_ORIENTATION 16384 /* device-specific parameters */ @@ -232,8 +266,17 @@ struct bcm5974_config { int bt_datalen; /* data length of the button interface */ int tp_ep; /* the endpoint of the trackpad interface */ enum tp_type tp_type; /* type of trackpad interface */ - int tp_offset; /* offset to trackpad finger data */ + int tp_header; /* bytes in header block */ int tp_datalen; /* data length of the trackpad interface */ + int tp_button; /* offset to button data */ + int tp_fsize; /* bytes in single finger block */ + int tp_delta; /* offset from header to finger struct */ + int um_size; /* usb control message length */ + int um_req_val; /* usb control message value */ + int um_req_idx; /* usb control message index */ + int um_switch_idx; /* usb control message mode switch index */ + int um_switch_on; /* usb control message mode switch on */ + int um_switch_off; /* usb control message mode switch off */ struct bcm5974_param p; /* finger pressure limits */ struct bcm5974_param w; /* finger width limits */ struct bcm5974_param x; /* horizontal limits */ @@ -259,6 +302,24 @@ struct bcm5974 { int slots[MAX_FINGERS]; /* slot assignments */ }; +/* trackpad finger block data, le16-aligned */ +static const struct tp_finger *get_tp_finger(const struct bcm5974 *dev, int i) +{ + const struct bcm5974_config *c = &dev->cfg; + u8 *f_base = dev->tp_data + c->tp_header + c->tp_delta; + + return (const struct tp_finger *)(f_base + i * c->tp_fsize); +} + +#define DATAFORMAT(type) \ + type, \ + HEADER_##type, \ + HEADER_##type + (MAX_FINGERS) * (FSIZE_##type), \ + BUTTON_##type, \ + FSIZE_##type, \ + DELTA_##type, \ + USBMSG_##type + /* logical signal quality */ #define SN_PRESSURE 45 /* pressure signal-to-noise ratio */ #define SN_WIDTH 25 /* width signal-to-noise ratio */ @@ -273,7 +334,7 @@ static const struct bcm5974_config bcm5974_config_table[] = { USB_DEVICE_ID_APPLE_WELLSPRING_JIS, 0, 0x84, sizeof(struct bt_data), - 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS, + 0x81, DATAFORMAT(TYPE1), { SN_PRESSURE, 0, 256 }, { SN_WIDTH, 0, 2048 }, { SN_COORD, -4824, 5342 }, @@ -286,7 +347,7 @@ static const struct bcm5974_config bcm5974_config_table[] = { USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, 0, 0x84, sizeof(struct bt_data), - 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS, + 0x81, DATAFORMAT(TYPE1), { SN_PRESSURE, 0, 256 }, { SN_WIDTH, 0, 2048 }, { SN_COORD, -4824, 4824 }, @@ -299,7 +360,7 @@ static const struct bcm5974_config bcm5974_config_table[] = { USB_DEVICE_ID_APPLE_WELLSPRING3_JIS, HAS_INTEGRATED_BUTTON, 0x84, sizeof(struct bt_data), - 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, + 0x81, DATAFORMAT(TYPE2), { SN_PRESSURE, 0, 300 }, { SN_WIDTH, 0, 2048 }, { SN_COORD, -4460, 5166 }, @@ -312,7 +373,7 @@ static const struct bcm5974_config bcm5974_config_table[] = { USB_DEVICE_ID_APPLE_WELLSPRING4_JIS, HAS_INTEGRATED_BUTTON, 0x84, sizeof(struct bt_data), - 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, + 0x81, DATAFORMAT(TYPE2), { SN_PRESSURE, 0, 300 }, { SN_WIDTH, 0, 2048 }, { SN_COORD, -4620, 5140 }, @@ -325,7 +386,7 @@ static const struct bcm5974_config bcm5974_config_table[] = { USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS, HAS_INTEGRATED_BUTTON, 0x84, sizeof(struct bt_data), - 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, + 0x81, DATAFORMAT(TYPE2), { SN_PRESSURE, 0, 300 }, { SN_WIDTH, 0, 2048 }, { SN_COORD, -4616, 5112 }, @@ -338,7 +399,7 @@ static const struct bcm5974_config bcm5974_config_table[] = { USB_DEVICE_ID_APPLE_WELLSPRING5_JIS, HAS_INTEGRATED_BUTTON, 0x84, sizeof(struct bt_data), - 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, + 0x81, DATAFORMAT(TYPE2), { SN_PRESSURE, 0, 300 }, { SN_WIDTH, 0, 2048 }, { SN_COORD, -4415, 5050 }, @@ -351,7 +412,7 @@ static const struct bcm5974_config bcm5974_config_table[] = { USB_DEVICE_ID_APPLE_WELLSPRING6_JIS, HAS_INTEGRATED_BUTTON, 0x84, sizeof(struct bt_data), - 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, + 0x81, DATAFORMAT(TYPE2), { SN_PRESSURE, 0, 300 }, { SN_WIDTH, 0, 2048 }, { SN_COORD, -4620, 5140 }, @@ -364,7 +425,7 @@ static const struct bcm5974_config bcm5974_config_table[] = { USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS, HAS_INTEGRATED_BUTTON, 0x84, sizeof(struct bt_data), - 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, + 0x81, DATAFORMAT(TYPE2), { SN_PRESSURE, 0, 300 }, { SN_WIDTH, 0, 2048 }, { SN_COORD, -4750, 5280 }, @@ -377,7 +438,7 @@ static const struct bcm5974_config bcm5974_config_table[] = { USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS, HAS_INTEGRATED_BUTTON, 0x84, sizeof(struct bt_data), - 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, + 0x81, DATAFORMAT(TYPE2), { SN_PRESSURE, 0, 300 }, { SN_WIDTH, 0, 2048 }, { SN_COORD, -4620, 5140 }, @@ -390,7 +451,7 @@ static const struct bcm5974_config bcm5974_config_table[] = { USB_DEVICE_ID_APPLE_WELLSPRING7_JIS, HAS_INTEGRATED_BUTTON, 0x84, sizeof(struct bt_data), - 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, + 0x81, DATAFORMAT(TYPE2), { SN_PRESSURE, 0, 300 }, { SN_WIDTH, 0, 2048 }, { SN_COORD, -4750, 5280 }, @@ -403,7 +464,7 @@ static const struct bcm5974_config bcm5974_config_table[] = { USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS, HAS_INTEGRATED_BUTTON, 0x84, sizeof(struct bt_data), - 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, + 0x81, DATAFORMAT(TYPE2), { SN_PRESSURE, 0, 300 }, { SN_WIDTH, 0, 2048 }, { SN_COORD, -4750, 5280 }, @@ -416,13 +477,26 @@ static const struct bcm5974_config bcm5974_config_table[] = { USB_DEVICE_ID_APPLE_WELLSPRING8_JIS, HAS_INTEGRATED_BUTTON, 0, sizeof(struct bt_data), - 0x83, TYPE3, FINGER_TYPE3, FINGER_TYPE3 + SIZEOF_ALL_FINGERS, + 0x83, DATAFORMAT(TYPE3), { SN_PRESSURE, 0, 300 }, { SN_WIDTH, 0, 2048 }, { SN_COORD, -4620, 5140 }, { SN_COORD, -150, 6600 }, { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } }, + { + USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI, + USB_DEVICE_ID_APPLE_WELLSPRING9_ISO, + USB_DEVICE_ID_APPLE_WELLSPRING9_JIS, + HAS_INTEGRATED_BUTTON, + 0, sizeof(struct bt_data), + 0x83, DATAFORMAT(TYPE4), + { SN_PRESSURE, 0, 300 }, + { SN_WIDTH, 0, 2048 }, + { SN_COORD, -4828, 5345 }, + { SN_COORD, -203, 6803 }, + { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + }, {} }; @@ -549,19 +623,18 @@ static int report_tp_state(struct bcm5974 *dev, int size) struct input_dev *input = dev->input; int raw_n, i, n = 0; - if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0) + if (size < c->tp_header || (size - c->tp_header) % c->tp_fsize != 0) return -EIO; - /* finger data, le16-aligned */ - f = (const struct tp_finger *)(dev->tp_data + c->tp_offset); - raw_n = (size - c->tp_offset) / SIZEOF_FINGER; + raw_n = (size - c->tp_header) / c->tp_fsize; for (i = 0; i < raw_n; i++) { - if (raw2int(f[i].touch_major) == 0) + f = get_tp_finger(dev, i); + if (raw2int(f->touch_major) == 0) continue; - dev->pos[n].x = raw2int(f[i].abs_x); - dev->pos[n].y = c->y.min + c->y.max - raw2int(f[i].abs_y); - dev->index[n++] = &f[i]; + dev->pos[n].x = raw2int(f->abs_x); + dev->pos[n].y = c->y.min + c->y.max - raw2int(f->abs_y); + dev->index[n++] = f; } input_mt_assign_slots(input, dev->slots, dev->pos, n, 0); @@ -572,32 +645,22 @@ static int report_tp_state(struct bcm5974 *dev, int size) input_mt_sync_frame(input); - report_synaptics_data(input, c, f, raw_n); + report_synaptics_data(input, c, get_tp_finger(dev, 0), raw_n); - /* type 2 reports button events via ibt only */ - if (c->tp_type == TYPE2) { - int ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); + /* later types report button events via integrated button only */ + if (c->caps & HAS_INTEGRATED_BUTTON) { + int ibt = raw2int(dev->tp_data[c->tp_button]); input_report_key(input, BTN_LEFT, ibt); } - if (c->tp_type == TYPE3) - input_report_key(input, BTN_LEFT, dev->tp_data[BUTTON_TYPE3]); - input_sync(input); return 0; } -/* Wellspring initialization constants */ -#define BCM5974_WELLSPRING_MODE_READ_REQUEST_ID 1 -#define BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID 9 -#define BCM5974_WELLSPRING_MODE_REQUEST_VALUE 0x300 -#define BCM5974_WELLSPRING_MODE_REQUEST_INDEX 0 -#define BCM5974_WELLSPRING_MODE_VENDOR_VALUE 0x01 -#define BCM5974_WELLSPRING_MODE_NORMAL_VALUE 0x08 - static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on) { + const struct bcm5974_config *c = &dev->cfg; int retval = 0, size; char *data; @@ -605,7 +668,7 @@ static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on) if (dev->cfg.tp_type == TYPE3) return 0; - data = kmalloc(8, GFP_KERNEL); + data = kmalloc(c->um_size, GFP_KERNEL); if (!data) { dev_err(&dev->intf->dev, "out of memory\n"); retval = -ENOMEM; @@ -616,28 +679,24 @@ static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on) size = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), BCM5974_WELLSPRING_MODE_READ_REQUEST_ID, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - BCM5974_WELLSPRING_MODE_REQUEST_VALUE, - BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000); + c->um_req_val, c->um_req_idx, data, c->um_size, 5000); - if (size != 8) { + if (size != c->um_size) { dev_err(&dev->intf->dev, "could not read from device\n"); retval = -EIO; goto out; } /* apply the mode switch */ - data[0] = on ? - BCM5974_WELLSPRING_MODE_VENDOR_VALUE : - BCM5974_WELLSPRING_MODE_NORMAL_VALUE; + data[c->um_switch_idx] = on ? c->um_switch_on : c->um_switch_off; /* write configuration */ size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - BCM5974_WELLSPRING_MODE_REQUEST_VALUE, - BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000); + c->um_req_val, c->um_req_idx, data, c->um_size, 5000); - if (size != 8) { + if (size != c->um_size) { dev_err(&dev->intf->dev, "could not write to device\n"); retval = -EIO; goto out; diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 62641f2adaf7..5b5f403d8ce6 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -771,7 +771,7 @@ static const struct attribute_group *elan_sysfs_groups[] = { */ static void elan_report_contact(struct elan_tp_data *data, int contact_num, bool contact_valid, - bool hover_event, u8 *finger_data) + u8 *finger_data) { struct input_dev *input = data->input; unsigned int pos_x, pos_y; @@ -815,9 +815,7 @@ static void elan_report_contact(struct elan_tp_data *data, input_mt_report_slot_state(input, MT_TOOL_FINGER, true); input_report_abs(input, ABS_MT_POSITION_X, pos_x); input_report_abs(input, ABS_MT_POSITION_Y, data->max_y - pos_y); - input_report_abs(input, ABS_MT_DISTANCE, hover_event); - input_report_abs(input, ABS_MT_PRESSURE, - hover_event ? 0 : scaled_pressure); + input_report_abs(input, ABS_MT_PRESSURE, scaled_pressure); input_report_abs(input, ABS_TOOL_WIDTH, mk_x); input_report_abs(input, ABS_MT_TOUCH_MAJOR, major); input_report_abs(input, ABS_MT_TOUCH_MINOR, minor); @@ -839,14 +837,14 @@ static void elan_report_absolute(struct elan_tp_data *data, u8 *packet) hover_event = hover_info & 0x40; for (i = 0; i < ETP_MAX_FINGERS; i++) { contact_valid = tp_info & (1U << (3 + i)); - elan_report_contact(data, i, contact_valid, hover_event, - finger_data); + elan_report_contact(data, i, contact_valid, finger_data); if (contact_valid) finger_data += ETP_FINGER_DATA_LEN; } input_report_key(input, BTN_LEFT, tp_info & 0x01); + input_report_abs(input, ABS_DISTANCE, hover_event != 0); input_mt_report_pointer_emulation(input, true); input_sync(input); } @@ -922,6 +920,7 @@ static int elan_setup_input_device(struct elan_tp_data *data) input_abs_set_res(input, ABS_Y, data->y_res); input_set_abs_params(input, ABS_PRESSURE, 0, ETP_MAX_PRESSURE, 0, 0); input_set_abs_params(input, ABS_TOOL_WIDTH, 0, ETP_FINGER_WIDTH, 0, 0); + input_set_abs_params(input, ABS_DISTANCE, 0, 1, 0, 0); /* And MT parameters */ input_set_abs_params(input, ABS_MT_POSITION_X, 0, data->max_x, 0, 0); @@ -934,7 +933,6 @@ static int elan_setup_input_device(struct elan_tp_data *data) ETP_FINGER_WIDTH * max_width, 0, 0); input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, ETP_FINGER_WIDTH * min_width, 0, 0); - input_set_abs_params(input, ABS_MT_DISTANCE, 0, 1, 0, 0); data->input = input; diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index ce3d40004458..2955f1d0ca6c 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -783,19 +783,26 @@ static int elantech_packet_check_v4(struct psmouse *psmouse) struct elantech_data *etd = psmouse->private; unsigned char *packet = psmouse->packet; unsigned char packet_type = packet[3] & 0x03; + unsigned int ic_version; bool sanity_check; if (etd->tp_dev && (packet[3] & 0x0f) == 0x06) return PACKET_TRACKPOINT; + /* This represents the version of IC body. */ + ic_version = (etd->fw_version & 0x0f0000) >> 16; + /* * Sanity check based on the constant bits of a packet. * The constant bits change depending on the value of - * the hardware flag 'crc_enabled' but are the same for - * every packet, regardless of the type. + * the hardware flag 'crc_enabled' and the version of + * the IC body, but are the same for every packet, + * regardless of the type. */ if (etd->crc_enabled) sanity_check = ((packet[3] & 0x08) == 0x00); + else if (ic_version == 7 && etd->samples[1] == 0x2A) + sanity_check = ((packet[3] & 0x1c) == 0x10); else sanity_check = ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0x1c) == 0x10); @@ -1116,6 +1123,7 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse, * Avatar AVIU-145A2 0x361f00 ? clickpad * Fujitsu LIFEBOOK E544 0x470f00 d0, 12, 09 2 hw buttons * Fujitsu LIFEBOOK E554 0x570f01 40, 14, 0c 2 hw buttons + * Fujitsu T725 0x470f01 05, 12, 09 2 hw buttons * Fujitsu H730 0x570f00 c0, 14, 0c 3 hw buttons (**) * Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons * Lenovo L430 0x350f02 b9, 15, 0c 2 hw buttons (*) @@ -1167,7 +1175,7 @@ static int elantech_set_input_params(struct psmouse *psmouse) struct input_dev *dev = psmouse->dev; struct elantech_data *etd = psmouse->private; unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0; - unsigned int x_res = 0, y_res = 0; + unsigned int x_res = 31, y_res = 31; if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width)) return -1; @@ -1232,8 +1240,6 @@ static int elantech_set_input_params(struct psmouse *psmouse) /* For X to recognize me as touchpad. */ input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); - input_abs_set_res(dev, ABS_X, x_res); - input_abs_set_res(dev, ABS_Y, y_res); /* * range of pressure and width is the same as v2, * report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility. @@ -1246,8 +1252,6 @@ static int elantech_set_input_params(struct psmouse *psmouse) input_mt_init_slots(dev, ETP_MAX_FINGERS, 0); input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); - input_abs_set_res(dev, ABS_MT_POSITION_X, x_res); - input_abs_set_res(dev, ABS_MT_POSITION_Y, y_res); input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2, ETP_PMAX_V2, 0, 0); /* @@ -1259,6 +1263,13 @@ static int elantech_set_input_params(struct psmouse *psmouse) break; } + input_abs_set_res(dev, ABS_X, x_res); + input_abs_set_res(dev, ABS_Y, y_res); + if (etd->hw_version > 1) { + input_abs_set_res(dev, ABS_MT_POSITION_X, x_res); + input_abs_set_res(dev, ABS_MT_POSITION_Y, y_res); + } + etd->y_max = y_max; etd->width = width; @@ -1648,6 +1659,16 @@ int elantech_init(struct psmouse *psmouse) etd->capabilities[0], etd->capabilities[1], etd->capabilities[2]); + if (etd->hw_version != 1) { + if (etd->send_cmd(psmouse, ETP_SAMPLE_QUERY, etd->samples)) { + psmouse_err(psmouse, "failed to query sample data\n"); + goto init_fail; + } + psmouse_info(psmouse, + "Elan sample query result %02x, %02x, %02x\n", + etd->samples[0], etd->samples[1], etd->samples[2]); + } + if (elantech_set_absolute_mode(psmouse)) { psmouse_err(psmouse, "failed to put touchpad into absolute mode.\n"); diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index f965d1569cc3..e1cbf409d9c8 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h @@ -129,6 +129,7 @@ struct elantech_data { unsigned char reg_26; unsigned char debug; unsigned char capabilities[3]; + unsigned char samples[3]; bool paritycheck; bool jumpy_cursor; bool reports_pressure; diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 35c8d0ceabee..6025eb430c0a 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -1199,7 +1199,7 @@ static void set_input_params(struct psmouse *psmouse, ABS_MT_POSITION_Y); /* Image sensors can report per-contact pressure */ input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0); - input_mt_init_slots(dev, 3, INPUT_MT_POINTER | INPUT_MT_TRACK); + input_mt_init_slots(dev, 2, INPUT_MT_POINTER | INPUT_MT_TRACK); /* Image sensors can signal 4 and 5 finger clicks */ __set_bit(BTN_TOOL_QUADTAP, dev->keybit); @@ -1484,12 +1484,12 @@ static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; psmouse_info(psmouse, - "Touchpad model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx, board id: %lu, fw id: %lu\n", + "Touchpad model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx/%#lx, board id: %lu, fw id: %lu\n", SYN_ID_MODEL(priv->identity), SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity), priv->model_id, priv->capabilities, priv->ext_cap, priv->ext_cap_0c, - priv->board_id, priv->firmware_id); + priv->ext_cap_10, priv->board_id, priv->firmware_id); set_input_params(psmouse, priv); diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index b4d12e29abff..e36162b28c2a 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -15,6 +15,7 @@ */ #include <linux/kernel.h> +#include <linux/dmi.h> #include <linux/i2c.h> #include <linux/input.h> #include <linux/input/mt.h> @@ -34,6 +35,7 @@ struct goodix_ts_data { int abs_y_max; unsigned int max_touch_num; unsigned int int_trigger_type; + bool rotated_screen; }; #define GOODIX_MAX_HEIGHT 4096 @@ -60,6 +62,30 @@ static const unsigned long goodix_irq_flags[] = { IRQ_TYPE_LEVEL_HIGH, }; +/* + * Those tablets have their coordinates origin at the bottom right + * of the tablet, as if rotated 180 degrees + */ +static const struct dmi_system_id rotated_screen[] = { +#if defined(CONFIG_DMI) && defined(CONFIG_X86) + { + .ident = "WinBook TW100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "WinBook"), + DMI_MATCH(DMI_PRODUCT_NAME, "TW100") + } + }, + { + .ident = "WinBook TW700", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "WinBook"), + DMI_MATCH(DMI_PRODUCT_NAME, "TW700") + }, + }, +#endif + {} +}; + /** * goodix_i2c_read - read data from a register of the i2c slave device. * @@ -129,6 +155,11 @@ static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data) int input_y = get_unaligned_le16(&coor_data[3]); int input_w = get_unaligned_le16(&coor_data[5]); + if (ts->rotated_screen) { + input_x = ts->abs_x_max - input_x; + input_y = ts->abs_y_max - input_y; + } + input_mt_slot(ts->input_dev, id); input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true); input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x); @@ -223,6 +254,11 @@ static void goodix_read_config(struct goodix_ts_data *ts) ts->abs_y_max = GOODIX_MAX_HEIGHT; ts->max_touch_num = GOODIX_MAX_CONTACTS; } + + ts->rotated_screen = dmi_check_system(rotated_screen); + if (ts->rotated_screen) + dev_dbg(&ts->client->dev, + "Applying '180 degrees rotated screen' quirk\n"); } /** diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index f2c6c352c55a..2c41107240de 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -627,6 +627,9 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) goto err_out; } + /* TSC-25 data sheet specifies a delay after the RESET command */ + msleep(150); + /* set coordinate output rate */ buf[0] = buf[1] = 0xFF; ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index a57e9b749895..658ee39e6569 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -76,8 +76,6 @@ LIST_HEAD(hpet_map); * Domain for untranslated devices - only allocated * if iommu=pt passed on kernel cmd line. */ -static struct protection_domain *pt_domain; - static const struct iommu_ops amd_iommu_ops; static ATOMIC_NOTIFIER_HEAD(ppr_notifier); @@ -96,7 +94,7 @@ struct iommu_dev_data { struct protection_domain *domain; /* Domain the device is bound to */ u16 devid; /* PCI Device ID */ bool iommu_v2; /* Device can make use of IOMMUv2 */ - bool passthrough; /* Default for device is pt_domain */ + bool passthrough; /* Device is identity mapped */ struct { bool enabled; int qdep; @@ -116,7 +114,6 @@ struct iommu_cmd { struct kmem_cache *amd_iommu_irq_cache; static void update_domain(struct protection_domain *domain); -static int alloc_passthrough_domain(void); static int protection_domain_init(struct protection_domain *domain); /**************************************************************************** @@ -2167,15 +2164,17 @@ static int attach_device(struct device *dev, dev_data = get_dev_data(dev); if (domain->flags & PD_IOMMUV2_MASK) { - if (!dev_data->iommu_v2 || !dev_data->passthrough) + if (!dev_data->passthrough) return -EINVAL; - if (pdev_iommuv2_enable(pdev) != 0) - return -EINVAL; + if (dev_data->iommu_v2) { + if (pdev_iommuv2_enable(pdev) != 0) + return -EINVAL; - dev_data->ats.enabled = true; - dev_data->ats.qdep = pci_ats_queue_depth(pdev); - dev_data->pri_tlp = pci_pri_tlp_required(pdev); + dev_data->ats.enabled = true; + dev_data->ats.qdep = pci_ats_queue_depth(pdev); + dev_data->pri_tlp = pci_pri_tlp_required(pdev); + } } else if (amd_iommu_iotlb_sup && pci_enable_ats(pdev, PAGE_SHIFT) == 0) { dev_data->ats.enabled = true; @@ -2221,15 +2220,6 @@ static void __detach_device(struct iommu_dev_data *dev_data) do_detach(head); spin_unlock_irqrestore(&domain->lock, flags); - - /* - * If we run in passthrough mode the device must be assigned to the - * passthrough domain if it is detached from any other domain. - * Make sure we can deassign from the pt_domain itself. - */ - if (dev_data->passthrough && - (dev_data->domain == NULL && domain != pt_domain)) - __attach_device(dev_data, pt_domain); } /* @@ -2249,7 +2239,7 @@ static void detach_device(struct device *dev) __detach_device(dev_data); write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); - if (domain->flags & PD_IOMMUV2_MASK) + if (domain->flags & PD_IOMMUV2_MASK && dev_data->iommu_v2) pdev_iommuv2_disable(to_pci_dev(dev)); else if (dev_data->ats.enabled) pci_disable_ats(to_pci_dev(dev)); @@ -2287,17 +2277,15 @@ static int amd_iommu_add_device(struct device *dev) BUG_ON(!dev_data); - if (dev_data->iommu_v2) + if (iommu_pass_through || dev_data->iommu_v2) iommu_request_dm_for_dev(dev); /* Domains are initialized for this device - have a look what we ended up with */ domain = iommu_get_domain_for_dev(dev); - if (domain->type == IOMMU_DOMAIN_IDENTITY) { + if (domain->type == IOMMU_DOMAIN_IDENTITY) dev_data->passthrough = true; - dev->archdata.dma_ops = &nommu_dma_ops; - } else { + else dev->archdata.dma_ops = &amd_iommu_dma_ops; - } out: iommu_completion_wait(iommu); @@ -2862,8 +2850,17 @@ int __init amd_iommu_init_api(void) int __init amd_iommu_init_dma_ops(void) { + swiotlb = iommu_pass_through ? 1 : 0; iommu_detected = 1; - swiotlb = 0; + + /* + * In case we don't initialize SWIOTLB (actually the common case + * when AMD IOMMU is enabled), make sure there are global + * dma_ops set as a fall-back for devices not handled by this + * driver (for example non-PCI devices). + */ + if (!swiotlb) + dma_ops = &nommu_dma_ops; amd_iommu_stats_init(); @@ -2947,21 +2944,6 @@ out_err: return NULL; } -static int alloc_passthrough_domain(void) -{ - if (pt_domain != NULL) - return 0; - - /* allocate passthrough domain */ - pt_domain = protection_domain_alloc(); - if (!pt_domain) - return -ENOMEM; - - pt_domain->mode = PAGE_MODE_NONE; - - return 0; -} - static struct iommu_domain *amd_iommu_domain_alloc(unsigned type) { struct protection_domain *pdomain; @@ -3222,33 +3204,6 @@ static const struct iommu_ops amd_iommu_ops = { * *****************************************************************************/ -int __init amd_iommu_init_passthrough(void) -{ - struct iommu_dev_data *dev_data; - struct pci_dev *dev = NULL; - int ret; - - ret = alloc_passthrough_domain(); - if (ret) - return ret; - - for_each_pci_dev(dev) { - if (!check_device(&dev->dev)) - continue; - - dev_data = get_dev_data(&dev->dev); - dev_data->passthrough = true; - - attach_device(&dev->dev, pt_domain); - } - - amd_iommu_stats_init(); - - pr_info("AMD-Vi: Initialized for Passthrough Mode\n"); - - return 0; -} - /* IOMMUv2 specific functions */ int amd_iommu_register_ppr_notifier(struct notifier_block *nb) { @@ -3363,7 +3318,12 @@ static int __flush_pasid(struct protection_domain *domain, int pasid, struct amd_iommu *iommu; int qdep; - BUG_ON(!dev_data->ats.enabled); + /* + There might be non-IOMMUv2 capable devices in an IOMMUv2 + * domain. + */ + if (!dev_data->ats.enabled) + continue; qdep = dev_data->ats.qdep; iommu = amd_iommu_rlookup_table[dev_data->devid]; diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index dbda9ae68c5d..a24495eb4e26 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -2026,14 +2026,6 @@ static bool detect_ivrs(void) return true; } -static int amd_iommu_init_dma(void) -{ - if (iommu_pass_through) - return amd_iommu_init_passthrough(); - else - return amd_iommu_init_dma_ops(); -} - /**************************************************************************** * * AMD IOMMU Initialization State Machine @@ -2073,7 +2065,7 @@ static int __init state_next(void) init_state = ret ? IOMMU_INIT_ERROR : IOMMU_INTERRUPTS_EN; break; case IOMMU_INTERRUPTS_EN: - ret = amd_iommu_init_dma(); + ret = amd_iommu_init_dma_ops(); init_state = ret ? IOMMU_INIT_ERROR : IOMMU_DMA_OPS; break; case IOMMU_DMA_OPS: diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c index 3465faf1809e..f7b875bb70d4 100644 --- a/drivers/iommu/amd_iommu_v2.c +++ b/drivers/iommu/amd_iommu_v2.c @@ -132,11 +132,19 @@ static struct device_state *get_device_state(u16 devid) static void free_device_state(struct device_state *dev_state) { + struct iommu_group *group; + /* * First detach device from domain - No more PRI requests will arrive * from that device after it is unbound from the IOMMUv2 domain. */ - iommu_detach_device(dev_state->domain, &dev_state->pdev->dev); + group = iommu_group_get(&dev_state->pdev->dev); + if (WARN_ON(!group)) + return; + + iommu_detach_group(dev_state->domain, group); + + iommu_group_put(group); /* Everything is down now, free the IOMMUv2 domain */ iommu_domain_free(dev_state->domain); @@ -731,6 +739,7 @@ EXPORT_SYMBOL(amd_iommu_unbind_pasid); int amd_iommu_init_device(struct pci_dev *pdev, int pasids) { struct device_state *dev_state; + struct iommu_group *group; unsigned long flags; int ret, tmp; u16 devid; @@ -776,10 +785,16 @@ int amd_iommu_init_device(struct pci_dev *pdev, int pasids) if (ret) goto out_free_domain; - ret = iommu_attach_device(dev_state->domain, &pdev->dev); - if (ret != 0) + group = iommu_group_get(&pdev->dev); + if (!group) goto out_free_domain; + ret = iommu_attach_group(dev_state->domain, group); + if (ret != 0) + goto out_drop_group; + + iommu_group_put(group); + spin_lock_irqsave(&state_lock, flags); if (__get_device_state(devid) != NULL) { @@ -794,6 +809,9 @@ int amd_iommu_init_device(struct pci_dev *pdev, int pasids) return 0; +out_drop_group: + iommu_group_put(group); + out_free_domain: iommu_domain_free(dev_state->domain); diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 8e9ec81ce4bb..da902baaa794 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -199,9 +199,10 @@ * Stream table. * * Linear: Enough to cover 1 << IDR1.SIDSIZE entries - * 2lvl: 8k L1 entries, 256 lazy entries per table (each table covers a PCI bus) + * 2lvl: 128k L1 entries, + * 256 lazy entries per table (each table covers a PCI bus) */ -#define STRTAB_L1_SZ_SHIFT 16 +#define STRTAB_L1_SZ_SHIFT 20 #define STRTAB_SPLIT 8 #define STRTAB_L1_DESC_DWORDS 1 @@ -269,10 +270,10 @@ #define ARM64_TCR_TG0_SHIFT 14 #define ARM64_TCR_TG0_MASK 0x3UL #define CTXDESC_CD_0_TCR_IRGN0_SHIFT 8 -#define ARM64_TCR_IRGN0_SHIFT 24 +#define ARM64_TCR_IRGN0_SHIFT 8 #define ARM64_TCR_IRGN0_MASK 0x3UL #define CTXDESC_CD_0_TCR_ORGN0_SHIFT 10 -#define ARM64_TCR_ORGN0_SHIFT 26 +#define ARM64_TCR_ORGN0_SHIFT 10 #define ARM64_TCR_ORGN0_MASK 0x3UL #define CTXDESC_CD_0_TCR_SH0_SHIFT 12 #define ARM64_TCR_SH0_SHIFT 12 @@ -542,6 +543,9 @@ struct arm_smmu_device { #define ARM_SMMU_FEAT_HYP (1 << 12) u32 features; +#define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0) + u32 options; + struct arm_smmu_cmdq cmdq; struct arm_smmu_evtq evtq; struct arm_smmu_priq priq; @@ -602,11 +606,35 @@ struct arm_smmu_domain { static DEFINE_SPINLOCK(arm_smmu_devices_lock); static LIST_HEAD(arm_smmu_devices); +struct arm_smmu_option_prop { + u32 opt; + const char *prop; +}; + +static struct arm_smmu_option_prop arm_smmu_options[] = { + { ARM_SMMU_OPT_SKIP_PREFETCH, "hisilicon,broken-prefetch-cmd" }, + { 0, NULL}, +}; + static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom) { return container_of(dom, struct arm_smmu_domain, domain); } +static void parse_driver_options(struct arm_smmu_device *smmu) +{ + int i = 0; + + do { + if (of_property_read_bool(smmu->dev->of_node, + arm_smmu_options[i].prop)) { + smmu->options |= arm_smmu_options[i].opt; + dev_notice(smmu->dev, "option %s\n", + arm_smmu_options[i].prop); + } + } while (arm_smmu_options[++i].opt); +} + /* Low-level queue manipulation functions */ static bool queue_full(struct arm_smmu_queue *q) { @@ -1036,7 +1064,8 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, arm_smmu_sync_ste_for_sid(smmu, sid); /* It's likely that we'll want to use the new STE soon */ - arm_smmu_cmdq_issue_cmd(smmu, &prefetch_cmd); + if (!(smmu->options & ARM_SMMU_OPT_SKIP_PREFETCH)) + arm_smmu_cmdq_issue_cmd(smmu, &prefetch_cmd); } static void arm_smmu_init_bypass_stes(u64 *strtab, unsigned int nent) @@ -1064,7 +1093,7 @@ static int arm_smmu_init_l2_strtab(struct arm_smmu_device *smmu, u32 sid) return 0; size = 1 << (STRTAB_SPLIT + ilog2(STRTAB_STE_DWORDS) + 3); - strtab = &cfg->strtab[sid >> STRTAB_SPLIT << STRTAB_L1_DESC_DWORDS]; + strtab = &cfg->strtab[(sid >> STRTAB_SPLIT) * STRTAB_L1_DESC_DWORDS]; desc->span = STRTAB_SPLIT + 1; desc->l2ptr = dma_zalloc_coherent(smmu->dev, size, &desc->l2ptr_dma, @@ -2020,21 +2049,23 @@ static int arm_smmu_init_strtab_2lvl(struct arm_smmu_device *smmu) { void *strtab; u64 reg; - u32 size; + u32 size, l1size; int ret; struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg; /* Calculate the L1 size, capped to the SIDSIZE */ size = STRTAB_L1_SZ_SHIFT - (ilog2(STRTAB_L1_DESC_DWORDS) + 3); size = min(size, smmu->sid_bits - STRTAB_SPLIT); - if (size + STRTAB_SPLIT < smmu->sid_bits) + cfg->num_l1_ents = 1 << size; + + size += STRTAB_SPLIT; + if (size < smmu->sid_bits) dev_warn(smmu->dev, "2-level strtab only covers %u/%u bits of SID\n", - size + STRTAB_SPLIT, smmu->sid_bits); + size, smmu->sid_bits); - cfg->num_l1_ents = 1 << size; - size = cfg->num_l1_ents * (STRTAB_L1_DESC_DWORDS << 3); - strtab = dma_zalloc_coherent(smmu->dev, size, &cfg->strtab_dma, + l1size = cfg->num_l1_ents * (STRTAB_L1_DESC_DWORDS << 3); + strtab = dma_zalloc_coherent(smmu->dev, l1size, &cfg->strtab_dma, GFP_KERNEL); if (!strtab) { dev_err(smmu->dev, @@ -2055,8 +2086,7 @@ static int arm_smmu_init_strtab_2lvl(struct arm_smmu_device *smmu) ret = arm_smmu_init_l1_strtab(smmu); if (ret) dma_free_coherent(smmu->dev, - cfg->num_l1_ents * - (STRTAB_L1_DESC_DWORDS << 3), + l1size, strtab, cfg->strtab_dma); return ret; @@ -2573,6 +2603,8 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) if (irq > 0) smmu->gerr_irq = irq; + parse_driver_options(smmu); + /* Probe the h/w */ ret = arm_smmu_device_probe(smmu); if (ret) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index a98a7b27aca1..0649b94f5958 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -1830,8 +1830,9 @@ static int domain_init(struct dmar_domain *domain, int guest_width) static void domain_exit(struct dmar_domain *domain) { + struct dmar_drhd_unit *drhd; + struct intel_iommu *iommu; struct page *freelist = NULL; - int i; /* Domain 0 is reserved, so dont process it */ if (!domain) @@ -1851,8 +1852,10 @@ static void domain_exit(struct dmar_domain *domain) /* clear attached or cached domains */ rcu_read_lock(); - for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus) - iommu_detach_domain(domain, g_iommus[i]); + for_each_active_iommu(iommu, drhd) + if (domain_type_is_vm(domain) || + test_bit(iommu->seq_id, domain->iommu_bmp)) + iommu_detach_domain(domain, iommu); rcu_read_unlock(); dma_free_pagelist(freelist); diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 1b7e155869f6..c00e2db351ba 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -75,6 +75,13 @@ struct its_node { #define ITS_ITT_ALIGN SZ_256 +struct event_lpi_map { + unsigned long *lpi_map; + u16 *col_map; + irq_hw_number_t lpi_base; + int nr_lpis; +}; + /* * The ITS view of a device - belongs to an ITS, a collection, owns an * interrupt translation table, and a list of interrupts. @@ -82,11 +89,8 @@ struct its_node { struct its_device { struct list_head entry; struct its_node *its; - struct its_collection *collection; + struct event_lpi_map event_map; void *itt; - unsigned long *lpi_map; - irq_hw_number_t lpi_base; - int nr_lpis; u32 nr_ites; u32 device_id; }; @@ -99,6 +103,14 @@ static struct rdists *gic_rdists; #define gic_data_rdist() (raw_cpu_ptr(gic_rdists->rdist)) #define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base) +static struct its_collection *dev_event_to_col(struct its_device *its_dev, + u32 event) +{ + struct its_node *its = its_dev->its; + + return its->collections + its_dev->event_map.col_map[event]; +} + /* * ITS command descriptors - parameters to be encoded in a command * block. @@ -134,7 +146,7 @@ struct its_cmd_desc { struct { struct its_device *dev; struct its_collection *col; - u32 id; + u32 event_id; } its_movi_cmd; struct { @@ -241,7 +253,7 @@ static struct its_collection *its_build_mapd_cmd(struct its_cmd_block *cmd, its_fixup_cmd(cmd); - return desc->its_mapd_cmd.dev->collection; + return NULL; } static struct its_collection *its_build_mapc_cmd(struct its_cmd_block *cmd, @@ -260,52 +272,72 @@ static struct its_collection *its_build_mapc_cmd(struct its_cmd_block *cmd, static struct its_collection *its_build_mapvi_cmd(struct its_cmd_block *cmd, struct its_cmd_desc *desc) { + struct its_collection *col; + + col = dev_event_to_col(desc->its_mapvi_cmd.dev, + desc->its_mapvi_cmd.event_id); + its_encode_cmd(cmd, GITS_CMD_MAPVI); its_encode_devid(cmd, desc->its_mapvi_cmd.dev->device_id); its_encode_event_id(cmd, desc->its_mapvi_cmd.event_id); its_encode_phys_id(cmd, desc->its_mapvi_cmd.phys_id); - its_encode_collection(cmd, desc->its_mapvi_cmd.dev->collection->col_id); + its_encode_collection(cmd, col->col_id); its_fixup_cmd(cmd); - return desc->its_mapvi_cmd.dev->collection; + return col; } static struct its_collection *its_build_movi_cmd(struct its_cmd_block *cmd, struct its_cmd_desc *desc) { + struct its_collection *col; + + col = dev_event_to_col(desc->its_movi_cmd.dev, + desc->its_movi_cmd.event_id); + its_encode_cmd(cmd, GITS_CMD_MOVI); its_encode_devid(cmd, desc->its_movi_cmd.dev->device_id); - its_encode_event_id(cmd, desc->its_movi_cmd.id); + its_encode_event_id(cmd, desc->its_movi_cmd.event_id); its_encode_collection(cmd, desc->its_movi_cmd.col->col_id); its_fixup_cmd(cmd); - return desc->its_movi_cmd.dev->collection; + return col; } static struct its_collection *its_build_discard_cmd(struct its_cmd_block *cmd, struct its_cmd_desc *desc) { + struct its_collection *col; + + col = dev_event_to_col(desc->its_discard_cmd.dev, + desc->its_discard_cmd.event_id); + its_encode_cmd(cmd, GITS_CMD_DISCARD); its_encode_devid(cmd, desc->its_discard_cmd.dev->device_id); its_encode_event_id(cmd, desc->its_discard_cmd.event_id); its_fixup_cmd(cmd); - return desc->its_discard_cmd.dev->collection; + return col; } static struct its_collection *its_build_inv_cmd(struct its_cmd_block *cmd, struct its_cmd_desc *desc) { + struct its_collection *col; + + col = dev_event_to_col(desc->its_inv_cmd.dev, + desc->its_inv_cmd.event_id); + its_encode_cmd(cmd, GITS_CMD_INV); its_encode_devid(cmd, desc->its_inv_cmd.dev->device_id); its_encode_event_id(cmd, desc->its_inv_cmd.event_id); its_fixup_cmd(cmd); - return desc->its_inv_cmd.dev->collection; + return col; } static struct its_collection *its_build_invall_cmd(struct its_cmd_block *cmd, @@ -497,7 +529,7 @@ static void its_send_movi(struct its_device *dev, desc.its_movi_cmd.dev = dev; desc.its_movi_cmd.col = col; - desc.its_movi_cmd.id = id; + desc.its_movi_cmd.event_id = id; its_send_single_command(dev->its, its_build_movi_cmd, &desc); } @@ -528,7 +560,7 @@ static void its_send_invall(struct its_node *its, struct its_collection *col) static inline u32 its_get_event_id(struct irq_data *d) { struct its_device *its_dev = irq_data_get_irq_chip_data(d); - return d->hwirq - its_dev->lpi_base; + return d->hwirq - its_dev->event_map.lpi_base; } static void lpi_set_config(struct irq_data *d, bool enable) @@ -583,7 +615,7 @@ static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val, target_col = &its_dev->its->collections[cpu]; its_send_movi(its_dev, target_col, id); - its_dev->collection = target_col; + its_dev->event_map.col_map[id] = cpu; return IRQ_SET_MASK_OK_DONE; } @@ -713,8 +745,10 @@ out: return bitmap; } -static void its_lpi_free(unsigned long *bitmap, int base, int nr_ids) +static void its_lpi_free(struct event_lpi_map *map) { + int base = map->lpi_base; + int nr_ids = map->nr_lpis; int lpi; spin_lock(&lpi_lock); @@ -731,7 +765,8 @@ static void its_lpi_free(unsigned long *bitmap, int base, int nr_ids) spin_unlock(&lpi_lock); - kfree(bitmap); + kfree(map->lpi_map); + kfree(map->col_map); } /* @@ -1099,11 +1134,11 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, struct its_device *dev; unsigned long *lpi_map; unsigned long flags; + u16 *col_map = NULL; void *itt; int lpi_base; int nr_lpis; int nr_ites; - int cpu; int sz; dev = kzalloc(sizeof(*dev), GFP_KERNEL); @@ -1117,20 +1152,24 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1; itt = kzalloc(sz, GFP_KERNEL); lpi_map = its_lpi_alloc_chunks(nvecs, &lpi_base, &nr_lpis); + if (lpi_map) + col_map = kzalloc(sizeof(*col_map) * nr_lpis, GFP_KERNEL); - if (!dev || !itt || !lpi_map) { + if (!dev || !itt || !lpi_map || !col_map) { kfree(dev); kfree(itt); kfree(lpi_map); + kfree(col_map); return NULL; } dev->its = its; dev->itt = itt; dev->nr_ites = nr_ites; - dev->lpi_map = lpi_map; - dev->lpi_base = lpi_base; - dev->nr_lpis = nr_lpis; + dev->event_map.lpi_map = lpi_map; + dev->event_map.col_map = col_map; + dev->event_map.lpi_base = lpi_base; + dev->event_map.nr_lpis = nr_lpis; dev->device_id = dev_id; INIT_LIST_HEAD(&dev->entry); @@ -1138,10 +1177,6 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, list_add(&dev->entry, &its->its_device_list); raw_spin_unlock_irqrestore(&its->lock, flags); - /* Bind the device to the first possible CPU */ - cpu = cpumask_first(cpu_online_mask); - dev->collection = &its->collections[cpu]; - /* Map device to its ITT */ its_send_mapd(dev, 1); @@ -1163,12 +1198,13 @@ static int its_alloc_device_irq(struct its_device *dev, irq_hw_number_t *hwirq) { int idx; - idx = find_first_zero_bit(dev->lpi_map, dev->nr_lpis); - if (idx == dev->nr_lpis) + idx = find_first_zero_bit(dev->event_map.lpi_map, + dev->event_map.nr_lpis); + if (idx == dev->event_map.nr_lpis) return -ENOSPC; - *hwirq = dev->lpi_base + idx; - set_bit(idx, dev->lpi_map); + *hwirq = dev->event_map.lpi_base + idx; + set_bit(idx, dev->event_map.lpi_map); return 0; } @@ -1288,7 +1324,8 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq, &its_irq_chip, its_dev); dev_dbg(info->scratchpad[1].ptr, "ID:%d pID:%d vID:%d\n", - (int)(hwirq - its_dev->lpi_base), (int)hwirq, virq + i); + (int)(hwirq - its_dev->event_map.lpi_base), + (int)hwirq, virq + i); } return 0; @@ -1300,6 +1337,9 @@ static void its_irq_domain_activate(struct irq_domain *domain, struct its_device *its_dev = irq_data_get_irq_chip_data(d); u32 event = its_get_event_id(d); + /* Bind the LPI to the first possible CPU */ + its_dev->event_map.col_map[event] = cpumask_first(cpu_online_mask); + /* Map the GIC IRQ and event to the device */ its_send_mapvi(its_dev, d->hwirq, event); } @@ -1327,17 +1367,16 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq, u32 event = its_get_event_id(data); /* Mark interrupt index as unused */ - clear_bit(event, its_dev->lpi_map); + clear_bit(event, its_dev->event_map.lpi_map); /* Nuke the entry in the domain */ irq_domain_reset_irq_data(data); } /* If all interrupts have been freed, start mopping the floor */ - if (bitmap_empty(its_dev->lpi_map, its_dev->nr_lpis)) { - its_lpi_free(its_dev->lpi_map, - its_dev->lpi_base, - its_dev->nr_lpis); + if (bitmap_empty(its_dev->event_map.lpi_map, + its_dev->event_map.nr_lpis)) { + its_lpi_free(&its_dev->event_map); /* Unmap device/itt */ its_send_mapd(its_dev, 0); diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 8d7e1c8b6d56..4dd88264dff5 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -1055,7 +1055,7 @@ gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header, processor = (struct acpi_madt_generic_interrupt *)header; - if (BAD_MADT_ENTRY(processor, end)) + if (BAD_MADT_GICC_ENTRY(processor, end)) return -EINVAL; /* diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 4400edd1a6c7..ff4be0515a0d 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c @@ -257,16 +257,6 @@ int gic_get_c0_fdc_int(void) return MIPS_CPU_IRQ_BASE + cp0_fdc_irq; } - /* - * Some cores claim the FDC is routable but it doesn't actually seem to - * be connected. - */ - switch (current_cpu_type()) { - case CPU_INTERAPTIV: - case CPU_PROAPTIV: - return -1; - } - return irq_create_mapping(gic_irq_domain, GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_FDC)); } @@ -548,7 +538,7 @@ static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) static irqreturn_t ipi_call_interrupt(int irq, void *dev_id) { - smp_call_function_interrupt(); + generic_smp_call_function_interrupt(); return IRQ_HANDLED; } diff --git a/drivers/irqchip/spear-shirq.c b/drivers/irqchip/spear-shirq.c index a45121546caf..acb721b31bcf 100644 --- a/drivers/irqchip/spear-shirq.c +++ b/drivers/irqchip/spear-shirq.c @@ -2,7 +2,7 @@ * SPEAr platform shared irq layer source file * * Copyright (C) 2009-2012 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * Copyright (C) 2012 ST Microelectronics * Shiraz Hashim <shiraz.linux.kernel@gmail.com> diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index 8c91fd5eb6fd..375be509e95f 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c @@ -524,9 +524,18 @@ gigaset_tty_open(struct tty_struct *tty) cs->hw.ser->tty = tty; atomic_set(&cs->hw.ser->refcnt, 1); init_completion(&cs->hw.ser->dead_cmp); - tty->disc_data = cs; + /* Set the amount of data we're willing to receive per call + * from the hardware driver to half of the input buffer size + * to leave some reserve. + * Note: We don't do flow control towards the hardware driver. + * If more data is received than will fit into the input buffer, + * it will be dropped and an error will be logged. This should + * never happen as the device is slow and the buffer size ample. + */ + tty->receive_room = RBUFSIZE/2; + /* OK.. Initialization of the datastructures and the HW is done.. Now * startup system and notify the LL that we are ready to run */ @@ -598,28 +607,6 @@ static int gigaset_tty_hangup(struct tty_struct *tty) } /* - * Read on the tty. - * Unused, received data goes only to the Gigaset driver. - */ -static ssize_t -gigaset_tty_read(struct tty_struct *tty, struct file *file, - unsigned char __user *buf, size_t count) -{ - return -EAGAIN; -} - -/* - * Write on the tty. - * Unused, transmit data comes only from the Gigaset driver. - */ -static ssize_t -gigaset_tty_write(struct tty_struct *tty, struct file *file, - const unsigned char *buf, size_t count) -{ - return -EAGAIN; -} - -/* * Ioctl on the tty. * Called in process context only. * May be re-entered by multiple ioctl calling threads. @@ -752,8 +739,6 @@ static struct tty_ldisc_ops gigaset_ldisc = { .open = gigaset_tty_open, .close = gigaset_tty_close, .hangup = gigaset_tty_hangup, - .read = gigaset_tty_read, - .write = gigaset_tty_write, .ioctl = gigaset_tty_ioctl, .receive_buf = gigaset_tty_receive, .write_wakeup = gigaset_tty_wakeup, diff --git a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c index 1a57e88a38f7..cd35079c8c98 100644 --- a/drivers/macintosh/ans-lcd.c +++ b/drivers/macintosh/ans-lcd.c @@ -7,7 +7,7 @@ #include <linux/kernel.h> #include <linux/miscdevice.h> #include <linux/fcntl.h> -#include <linux/init.h> +#include <linux/module.h> #include <linux/delay.h> #include <linux/fs.h> diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index b59727309072..bfec3bdfe598 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig @@ -259,7 +259,7 @@ config DM_CRYPT the ciphers you're going to use in the cryptoapi configuration. For further information on dm-crypt and userspace tools see: - <http://code.google.com/p/cryptsetup/wiki/DMCrypt> + <https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt> To compile this code as a module, choose M here: the module will be called dm-crypt. diff --git a/drivers/md/bcache/closure.h b/drivers/md/bcache/closure.h index a08e3eeac3c5..79a6d63e8ed3 100644 --- a/drivers/md/bcache/closure.h +++ b/drivers/md/bcache/closure.h @@ -320,7 +320,6 @@ static inline void closure_wake_up(struct closure_waitlist *list) do { \ set_closure_fn(_cl, _fn, _wq); \ closure_sub(_cl, CLOSURE_RUNNING + 1); \ - return; \ } while (0) /** @@ -349,7 +348,6 @@ do { \ do { \ set_closure_fn(_cl, _fn, _wq); \ closure_queue(_cl); \ - return; \ } while (0) /** @@ -365,7 +363,6 @@ do { \ do { \ set_closure_fn(_cl, _destructor, NULL); \ closure_sub(_cl, CLOSURE_RUNNING - CLOSURE_DESTRUCTOR + 1); \ - return; \ } while (0) /** diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c index cb64e64a4789..bf6a9ca18403 100644 --- a/drivers/md/bcache/io.c +++ b/drivers/md/bcache/io.c @@ -105,6 +105,7 @@ void bch_generic_make_request(struct bio *bio, struct bio_split_pool *p) } while (n != bio); continue_at(&s->cl, bch_bio_submit_split_done, NULL); + return; submit: generic_make_request(bio); } diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c index ce64fc851251..418607a6ba33 100644 --- a/drivers/md/bcache/journal.c +++ b/drivers/md/bcache/journal.c @@ -592,12 +592,14 @@ static void journal_write_unlocked(struct closure *cl) if (!w->need_write) { closure_return_with_destructor(cl, journal_write_unlock); + return; } else if (journal_full(&c->journal)) { journal_reclaim(c); spin_unlock(&c->journal.lock); btree_flush_write(c); continue_at(cl, journal_write, system_wq); + return; } c->journal.blocks_free -= set_blocks(w->data, block_bytes(c)); diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index 4afb2d26b148..f292790997d7 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c @@ -88,8 +88,10 @@ static void bch_data_insert_keys(struct closure *cl) if (journal_ref) atomic_dec_bug(journal_ref); - if (!op->insert_data_done) + if (!op->insert_data_done) { continue_at(cl, bch_data_insert_start, op->wq); + return; + } bch_keylist_free(&op->insert_keys); closure_return(cl); @@ -216,8 +218,10 @@ static void bch_data_insert_start(struct closure *cl) /* 1 for the device pointer and 1 for the chksum */ if (bch_keylist_realloc(&op->insert_keys, 3 + (op->csum ? 1 : 0), - op->c)) + op->c)) { continue_at(cl, bch_data_insert_keys, op->wq); + return; + } k = op->insert_keys.top; bkey_init(k); @@ -255,6 +259,7 @@ static void bch_data_insert_start(struct closure *cl) op->insert_data_done = true; continue_at(cl, bch_data_insert_keys, op->wq); + return; err: /* bch_alloc_sectors() blocks if s->writeback = true */ BUG_ON(op->writeback); @@ -576,8 +581,10 @@ static void cache_lookup(struct closure *cl) ret = bch_btree_map_keys(&s->op, s->iop.c, &KEY(s->iop.inode, bio->bi_iter.bi_sector, 0), cache_lookup_fn, MAP_END_KEY); - if (ret == -EAGAIN) + if (ret == -EAGAIN) { continue_at(cl, cache_lookup, bcache_wq); + return; + } closure_return(cl); } @@ -1085,6 +1092,7 @@ static void flash_dev_make_request(struct request_queue *q, struct bio *bio) continue_at_nobarrier(&s->cl, flash_dev_nodata, bcache_wq); + return; } else if (rw) { bch_keybuf_check_overlapping(&s->iop.c->moving_gc_keys, &KEY(d->id, bio->bi_iter.bi_sector, 0), diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index ed2346ddf4c9..e51de52eeb94 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -494,7 +494,7 @@ static int bitmap_new_disk_sb(struct bitmap *bitmap) bitmap_super_t *sb; unsigned long chunksize, daemon_sleep, write_behind; - bitmap->storage.sb_page = alloc_page(GFP_KERNEL); + bitmap->storage.sb_page = alloc_page(GFP_KERNEL | __GFP_ZERO); if (bitmap->storage.sb_page == NULL) return -ENOMEM; bitmap->storage.sb_page->index = 0; @@ -541,6 +541,7 @@ static int bitmap_new_disk_sb(struct bitmap *bitmap) sb->state = cpu_to_le32(bitmap->flags); bitmap->events_cleared = bitmap->mddev->events; sb->events_cleared = cpu_to_le64(bitmap->mddev->events); + bitmap->mddev->bitmap_info.nodes = 0; kunmap_atomic(sb); @@ -558,6 +559,7 @@ static int bitmap_read_sb(struct bitmap *bitmap) unsigned long sectors_reserved = 0; int err = -EINVAL; struct page *sb_page; + loff_t offset = bitmap->mddev->bitmap_info.offset; if (!bitmap->storage.file && !bitmap->mddev->bitmap_info.offset) { chunksize = 128 * 1024 * 1024; @@ -584,9 +586,9 @@ re_read: bm_blocks = ((bm_blocks+7) >> 3) + sizeof(bitmap_super_t); /* to 4k blocks */ bm_blocks = DIV_ROUND_UP_SECTOR_T(bm_blocks, 4096); - bitmap->mddev->bitmap_info.offset += bitmap->cluster_slot * (bm_blocks << 3); + offset = bitmap->mddev->bitmap_info.offset + (bitmap->cluster_slot * (bm_blocks << 3)); pr_info("%s:%d bm slot: %d offset: %llu\n", __func__, __LINE__, - bitmap->cluster_slot, (unsigned long long)bitmap->mddev->bitmap_info.offset); + bitmap->cluster_slot, offset); } if (bitmap->storage.file) { @@ -597,7 +599,7 @@ re_read: bitmap, bytes, sb_page); } else { err = read_sb_page(bitmap->mddev, - bitmap->mddev->bitmap_info.offset, + offset, sb_page, 0, sizeof(bitmap_super_t)); } @@ -611,8 +613,16 @@ re_read: daemon_sleep = le32_to_cpu(sb->daemon_sleep) * HZ; write_behind = le32_to_cpu(sb->write_behind); sectors_reserved = le32_to_cpu(sb->sectors_reserved); - nodes = le32_to_cpu(sb->nodes); - strlcpy(bitmap->mddev->bitmap_info.cluster_name, sb->cluster_name, 64); + /* XXX: This is a hack to ensure that we don't use clustering + * in case: + * - dm-raid is in use and + * - the nodes written in bitmap_sb is erroneous. + */ + if (!bitmap->mddev->sync_super) { + nodes = le32_to_cpu(sb->nodes); + strlcpy(bitmap->mddev->bitmap_info.cluster_name, + sb->cluster_name, 64); + } /* verify that the bitmap-specific fields are valid */ if (sb->magic != cpu_to_le32(BITMAP_MAGIC)) @@ -671,7 +681,7 @@ out: kunmap_atomic(sb); /* Assiging chunksize is required for "re_read" */ bitmap->mddev->bitmap_info.chunksize = chunksize; - if (nodes && (bitmap->cluster_slot < 0)) { + if (err == 0 && nodes && (bitmap->cluster_slot < 0)) { err = md_setup_cluster(bitmap->mddev, nodes); if (err) { pr_err("%s: Could not setup cluster service (%d)\n", @@ -1866,10 +1876,6 @@ int bitmap_copy_from_slot(struct mddev *mddev, int slot, if (IS_ERR(bitmap)) return PTR_ERR(bitmap); - rv = bitmap_read_sb(bitmap); - if (rv) - goto err; - rv = bitmap_init_from_disk(bitmap, 0); if (rv) goto err; diff --git a/drivers/md/dm-cache-policy-smq.c b/drivers/md/dm-cache-policy-smq.c index b6f22651dd35..48a4a826ae07 100644 --- a/drivers/md/dm-cache-policy-smq.c +++ b/drivers/md/dm-cache-policy-smq.c @@ -1686,7 +1686,7 @@ static struct dm_cache_policy *smq_create(dm_cblock_t cache_size, if (from_cblock(cache_size)) { mq->cache_hit_bits = alloc_bitset(from_cblock(cache_size)); - if (!mq->cache_hit_bits && mq->cache_hit_bits) { + if (!mq->cache_hit_bits) { DMERR("couldn't allocate cache hit bitset"); goto bad_cache_hit_bits; } diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 1b4e1756b169..1fe93cfea7d3 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -1947,6 +1947,7 @@ static int commit_if_needed(struct cache *cache) static void process_deferred_bios(struct cache *cache) { + bool prealloc_used = false; unsigned long flags; struct bio_list bios; struct bio *bio; @@ -1966,6 +1967,7 @@ static void process_deferred_bios(struct cache *cache) * this bio might require one, we pause until there are some * prepared mappings to process. */ + prealloc_used = true; if (prealloc_data_structs(cache, &structs)) { spin_lock_irqsave(&cache->lock, flags); bio_list_merge(&cache->deferred_bios, &bios); @@ -1983,11 +1985,13 @@ static void process_deferred_bios(struct cache *cache) process_bio(cache, &structs, bio); } - prealloc_free_structs(cache, &structs); + if (prealloc_used) + prealloc_free_structs(cache, &structs); } static void process_deferred_cells(struct cache *cache) { + bool prealloc_used = false; unsigned long flags; struct dm_bio_prison_cell *cell, *tmp; struct list_head cells; @@ -2007,6 +2011,7 @@ static void process_deferred_cells(struct cache *cache) * this bio might require one, we pause until there are some * prepared mappings to process. */ + prealloc_used = true; if (prealloc_data_structs(cache, &structs)) { spin_lock_irqsave(&cache->lock, flags); list_splice(&cells, &cache->deferred_cells); @@ -2017,7 +2022,8 @@ static void process_deferred_cells(struct cache *cache) process_cell(cache, &structs, cell); } - prealloc_free_structs(cache, &structs); + if (prealloc_used) + prealloc_free_structs(cache, &structs); } static void process_deferred_flush_bios(struct cache *cache, bool submit_bios) @@ -2062,7 +2068,7 @@ static void process_deferred_writethrough_bios(struct cache *cache) static void writeback_some_dirty_blocks(struct cache *cache) { - int r = 0; + bool prealloc_used = false; dm_oblock_t oblock; dm_cblock_t cblock; struct prealloc structs; @@ -2072,15 +2078,12 @@ static void writeback_some_dirty_blocks(struct cache *cache) memset(&structs, 0, sizeof(structs)); while (spare_migration_bandwidth(cache)) { - if (prealloc_data_structs(cache, &structs)) - break; - - r = policy_writeback_work(cache->policy, &oblock, &cblock, busy); - if (r) - break; + if (policy_writeback_work(cache->policy, &oblock, &cblock, busy)) + break; /* no work to do */ - r = get_cell(cache, oblock, &structs, &old_ocell); - if (r) { + prealloc_used = true; + if (prealloc_data_structs(cache, &structs) || + get_cell(cache, oblock, &structs, &old_ocell)) { policy_set_dirty(cache->policy, oblock); break; } @@ -2088,7 +2091,8 @@ static void writeback_some_dirty_blocks(struct cache *cache) writeback(cache, &structs, oblock, cblock, old_ocell); } - prealloc_free_structs(cache, &structs); + if (prealloc_used) + prealloc_free_structs(cache, &structs); } /*---------------------------------------------------------------- @@ -3496,7 +3500,7 @@ static void cache_resume(struct dm_target *ti) * <#demotions> <#promotions> <#dirty> * <#features> <features>* * <#core args> <core args> - * <policy name> <#policy args> <policy args>* <cache metadata mode> + * <policy name> <#policy args> <policy args>* <cache metadata mode> <needs_check> */ static void cache_status(struct dm_target *ti, status_type_t type, unsigned status_flags, char *result, unsigned maxlen) @@ -3582,6 +3586,11 @@ static void cache_status(struct dm_target *ti, status_type_t type, else DMEMIT("rw "); + if (dm_cache_metadata_needs_check(cache->cmd)) + DMEMIT("needs_check "); + else + DMEMIT("- "); + break; case STATUSTYPE_TABLE: @@ -3820,7 +3829,7 @@ static void cache_io_hints(struct dm_target *ti, struct queue_limits *limits) static struct target_type cache_target = { .name = "cache", - .version = {1, 7, 0}, + .version = {1, 8, 0}, .module = THIS_MODULE, .ctr = cache_ctr, .dtr = cache_dtr, diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index c33f61a4cc28..d2bbe8cc1e97 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -18,6 +18,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/slab.h> +#include <linux/vmalloc.h> #include <linux/sort.h> #include <linux/rbtree.h> @@ -268,7 +269,7 @@ struct pool { process_mapping_fn process_prepared_mapping; process_mapping_fn process_prepared_discard; - struct dm_bio_prison_cell *cell_sort_array[CELL_SORT_ARRAY_SIZE]; + struct dm_bio_prison_cell **cell_sort_array; }; static enum pool_mode get_pool_mode(struct pool *pool); @@ -665,16 +666,21 @@ static void requeue_io(struct thin_c *tc) requeue_deferred_cells(tc); } -static void error_retry_list(struct pool *pool) +static void error_retry_list_with_code(struct pool *pool, int error) { struct thin_c *tc; rcu_read_lock(); list_for_each_entry_rcu(tc, &pool->active_thins, list) - error_thin_bio_list(tc, &tc->retry_on_resume_list, -EIO); + error_thin_bio_list(tc, &tc->retry_on_resume_list, error); rcu_read_unlock(); } +static void error_retry_list(struct pool *pool) +{ + return error_retry_list_with_code(pool, -EIO); +} + /* * This section of code contains the logic for processing a thin device's IO. * Much of the code depends on pool object resources (lists, workqueues, etc) @@ -2281,18 +2287,23 @@ static void do_waker(struct work_struct *ws) queue_delayed_work(pool->wq, &pool->waker, COMMIT_PERIOD); } +static void notify_of_pool_mode_change_to_oods(struct pool *pool); + /* * We're holding onto IO to allow userland time to react. After the * timeout either the pool will have been resized (and thus back in - * PM_WRITE mode), or we degrade to PM_READ_ONLY and start erroring IO. + * PM_WRITE mode), or we degrade to PM_OUT_OF_DATA_SPACE w/ error_if_no_space. */ static void do_no_space_timeout(struct work_struct *ws) { struct pool *pool = container_of(to_delayed_work(ws), struct pool, no_space_timeout); - if (get_pool_mode(pool) == PM_OUT_OF_DATA_SPACE && !pool->pf.error_if_no_space) - set_pool_mode(pool, PM_READ_ONLY); + if (get_pool_mode(pool) == PM_OUT_OF_DATA_SPACE && !pool->pf.error_if_no_space) { + pool->pf.error_if_no_space = true; + notify_of_pool_mode_change_to_oods(pool); + error_retry_list_with_code(pool, -ENOSPC); + } } /*----------------------------------------------------------------*/ @@ -2370,6 +2381,14 @@ static void notify_of_pool_mode_change(struct pool *pool, const char *new_mode) dm_device_name(pool->pool_md), new_mode); } +static void notify_of_pool_mode_change_to_oods(struct pool *pool) +{ + if (!pool->pf.error_if_no_space) + notify_of_pool_mode_change(pool, "out-of-data-space (queue IO)"); + else + notify_of_pool_mode_change(pool, "out-of-data-space (error IO)"); +} + static bool passdown_enabled(struct pool_c *pt) { return pt->adjusted_pf.discard_passdown; @@ -2454,7 +2473,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) * frequently seeing this mode. */ if (old_mode != new_mode) - notify_of_pool_mode_change(pool, "out-of-data-space"); + notify_of_pool_mode_change_to_oods(pool); pool->process_bio = process_bio_read_only; pool->process_discard = process_discard_bio; pool->process_cell = process_cell_read_only; @@ -2777,6 +2796,7 @@ static void __pool_destroy(struct pool *pool) { __pool_table_remove(pool); + vfree(pool->cell_sort_array); if (dm_pool_metadata_close(pool->pmd) < 0) DMWARN("%s: dm_pool_metadata_close() failed.", __func__); @@ -2889,6 +2909,13 @@ static struct pool *pool_create(struct mapped_device *pool_md, goto bad_mapping_pool; } + pool->cell_sort_array = vmalloc(sizeof(*pool->cell_sort_array) * CELL_SORT_ARRAY_SIZE); + if (!pool->cell_sort_array) { + *error = "Error allocating cell sort array"; + err_p = ERR_PTR(-ENOMEM); + goto bad_sort_array; + } + pool->ref_count = 1; pool->last_commit_jiffies = jiffies; pool->pool_md = pool_md; @@ -2897,6 +2924,8 @@ static struct pool *pool_create(struct mapped_device *pool_md, return pool; +bad_sort_array: + mempool_destroy(pool->mapping_pool); bad_mapping_pool: dm_deferred_set_destroy(pool->all_io_ds); bad_all_io_ds: @@ -3714,6 +3743,7 @@ static void emit_flags(struct pool_features *pf, char *result, * Status line is: * <transaction id> <used metadata sectors>/<total metadata sectors> * <used data sectors>/<total data sectors> <held metadata root> + * <pool mode> <discard config> <no space config> <needs_check> */ static void pool_status(struct dm_target *ti, status_type_t type, unsigned status_flags, char *result, unsigned maxlen) @@ -3815,6 +3845,11 @@ static void pool_status(struct dm_target *ti, status_type_t type, else DMEMIT("queue_if_no_space "); + if (dm_pool_metadata_needs_check(pool->pmd)) + DMEMIT("needs_check "); + else + DMEMIT("- "); + break; case STATUSTYPE_TABLE: @@ -3918,7 +3953,7 @@ static struct target_type pool_target = { .name = "thin-pool", .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE | DM_TARGET_IMMUTABLE, - .version = {1, 15, 0}, + .version = {1, 16, 0}, .module = THIS_MODULE, .ctr = pool_ctr, .dtr = pool_dtr, @@ -4305,7 +4340,7 @@ static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits) static struct target_type thin_target = { .name = "thin", - .version = {1, 15, 0}, + .version = {1, 16, 0}, .module = THIS_MODULE, .ctr = thin_ctr, .dtr = thin_dtr, diff --git a/drivers/md/dm.c b/drivers/md/dm.c index f331d888e7f5..0d7ab20c58df 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1067,13 +1067,10 @@ static void rq_end_stats(struct mapped_device *md, struct request *orig) */ static void rq_completed(struct mapped_device *md, int rw, bool run_queue) { - int nr_requests_pending; - atomic_dec(&md->pending[rw]); /* nudge anyone waiting on suspend queue */ - nr_requests_pending = md_in_flight(md); - if (!nr_requests_pending) + if (!md_in_flight(md)) wake_up(&md->wait); /* @@ -1085,8 +1082,7 @@ static void rq_completed(struct mapped_device *md, int rw, bool run_queue) if (run_queue) { if (md->queue->mq_ops) blk_mq_run_hw_queues(md->queue, true); - else if (!nr_requests_pending || - (nr_requests_pending >= md->queue->nr_congestion_on)) + else blk_run_queue_async(md->queue); } @@ -1733,7 +1729,8 @@ static int dm_merge_bvec(struct request_queue *q, struct mapped_device *md = q->queuedata; struct dm_table *map = dm_get_live_table_fast(md); struct dm_target *ti; - sector_t max_sectors, max_size = 0; + sector_t max_sectors; + int max_size = 0; if (unlikely(!map)) goto out; @@ -1746,18 +1743,10 @@ static int dm_merge_bvec(struct request_queue *q, * Find maximum amount of I/O that won't need splitting */ max_sectors = min(max_io_len(bvm->bi_sector, ti), - (sector_t) queue_max_sectors(q)); + (sector_t) BIO_MAX_SECTORS); max_size = (max_sectors << SECTOR_SHIFT) - bvm->bi_size; - - /* - * FIXME: this stop-gap fix _must_ be cleaned up (by passing a sector_t - * to the targets' merge function since it holds sectors not bytes). - * Just doing this as an interim fix for stable@ because the more - * comprehensive cleanup of switching to sector_t will impact every - * DM target that implements a ->merge hook. - */ - if (max_size > INT_MAX) - max_size = INT_MAX; + if (max_size < 0) + max_size = 0; /* * merge_bvec_fn() returns number of bytes @@ -1765,13 +1754,13 @@ static int dm_merge_bvec(struct request_queue *q, * max is precomputed maximal io size */ if (max_size && ti->type->merge) - max_size = ti->type->merge(ti, bvm, biovec, (int) max_size); + max_size = ti->type->merge(ti, bvm, biovec, max_size); /* * If the target doesn't support merge method and some of the devices - * provided their merge_bvec method (we know this by looking for the - * max_hw_sectors that dm_set_device_limits may set), then we can't - * allow bios with multiple vector entries. So always set max_size - * to 0, and the code below allows just one page. + * provided their merge_bvec method (we know this by looking at + * queue_max_hw_sectors), then we can't allow bios with multiple vector + * entries. So always set max_size to 0, and the code below allows + * just one page. */ else if (queue_max_hw_sectors(q) <= PAGE_SIZE >> 9) max_size = 0; @@ -2281,8 +2270,6 @@ static void dm_init_old_md_queue(struct mapped_device *md) static void cleanup_mapped_device(struct mapped_device *md) { - cleanup_srcu_struct(&md->io_barrier); - if (md->wq) destroy_workqueue(md->wq); if (md->kworker_task) @@ -2294,6 +2281,8 @@ static void cleanup_mapped_device(struct mapped_device *md) if (md->bs) bioset_free(md->bs); + cleanup_srcu_struct(&md->io_barrier); + if (md->disk) { spin_lock(&_minor_lock); md->disk->private_data = NULL; diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c index fcfc4b9b2672..0072190515e0 100644 --- a/drivers/md/md-cluster.c +++ b/drivers/md/md-cluster.c @@ -44,6 +44,7 @@ struct resync_info { /* md_cluster_info flags */ #define MD_CLUSTER_WAITING_FOR_NEWDISK 1 +#define MD_CLUSTER_SUSPEND_READ_BALANCING 2 struct md_cluster_info { @@ -275,6 +276,9 @@ clear_bit: static void recover_prep(void *arg) { + struct mddev *mddev = arg; + struct md_cluster_info *cinfo = mddev->cluster_info; + set_bit(MD_CLUSTER_SUSPEND_READ_BALANCING, &cinfo->state); } static void recover_slot(void *arg, struct dlm_slot *slot) @@ -307,6 +311,7 @@ static void recover_done(void *arg, struct dlm_slot *slots, cinfo->slot_number = our_slot; complete(&cinfo->completion); + clear_bit(MD_CLUSTER_SUSPEND_READ_BALANCING, &cinfo->state); } static const struct dlm_lockspace_ops md_ls_ops = { @@ -816,12 +821,17 @@ static void resync_finish(struct mddev *mddev) resync_send(mddev, RESYNCING, 0, 0); } -static int area_resyncing(struct mddev *mddev, sector_t lo, sector_t hi) +static int area_resyncing(struct mddev *mddev, int direction, + sector_t lo, sector_t hi) { struct md_cluster_info *cinfo = mddev->cluster_info; int ret = 0; struct suspend_info *s; + if ((direction == READ) && + test_bit(MD_CLUSTER_SUSPEND_READ_BALANCING, &cinfo->state)) + return 1; + spin_lock_irq(&cinfo->suspend_lock); if (list_empty(&cinfo->suspend_list)) goto out; diff --git a/drivers/md/md-cluster.h b/drivers/md/md-cluster.h index 6817ee00e053..00defe2badbc 100644 --- a/drivers/md/md-cluster.h +++ b/drivers/md/md-cluster.h @@ -18,7 +18,7 @@ struct md_cluster_operations { int (*metadata_update_start)(struct mddev *mddev); int (*metadata_update_finish)(struct mddev *mddev); int (*metadata_update_cancel)(struct mddev *mddev); - int (*area_resyncing)(struct mddev *mddev, sector_t lo, sector_t hi); + int (*area_resyncing)(struct mddev *mddev, int direction, sector_t lo, sector_t hi); int (*add_new_disk_start)(struct mddev *mddev, struct md_rdev *rdev); int (*add_new_disk_finish)(struct mddev *mddev); int (*new_disk_ack)(struct mddev *mddev, bool ack); diff --git a/drivers/md/md.c b/drivers/md/md.c index d429c30cd514..e25f00f0138a 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5382,6 +5382,8 @@ static void __md_stop(struct mddev *mddev) { struct md_personality *pers = mddev->pers; mddev_detach(mddev); + /* Ensure ->event_work is done */ + flush_workqueue(md_misc_wq); spin_lock(&mddev->lock); mddev->ready = 0; mddev->pers = NULL; @@ -5757,7 +5759,7 @@ static int get_bitmap_file(struct mddev *mddev, void __user * arg) char *ptr; int err; - file = kmalloc(sizeof(*file), GFP_NOIO); + file = kzalloc(sizeof(*file), GFP_NOIO); if (!file) return -ENOMEM; @@ -7437,7 +7439,7 @@ int md_setup_cluster(struct mddev *mddev, int nodes) err = request_module("md-cluster"); if (err) { pr_err("md-cluster module not found.\n"); - return err; + return -ENOENT; } spin_lock(&pers_lock); diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c index e04cfd2d60ef..9ca9eccd512f 100644 --- a/drivers/md/persistent-data/dm-btree-remove.c +++ b/drivers/md/persistent-data/dm-btree-remove.c @@ -309,8 +309,8 @@ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent, if (s < 0 && nr_center < -s) { /* not enough in central node */ - shift(left, center, nr_center); - s = nr_center - target; + shift(left, center, -nr_center); + s += nr_center; shift(left, right, s); nr_right += s; } else @@ -323,7 +323,7 @@ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent, if (s > 0 && nr_center < s) { /* not enough in central node */ shift(center, right, nr_center); - s = target - nr_center; + s -= nr_center; shift(left, right, s); nr_left -= s; } else @@ -689,6 +689,7 @@ static int remove_one(struct dm_btree_info *info, dm_block_t root, value_ptr(n, index)); delete_at(n, index); + keys[last_level] = k + 1ull; } else r = -ENODATA; diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c index 200ac12a1d40..fdd3793e22f9 100644 --- a/drivers/md/persistent-data/dm-btree.c +++ b/drivers/md/persistent-data/dm-btree.c @@ -255,7 +255,7 @@ int dm_btree_del(struct dm_btree_info *info, dm_block_t root) int r; struct del_stack *s; - s = kmalloc(sizeof(*s), GFP_KERNEL); + s = kmalloc(sizeof(*s), GFP_NOIO); if (!s) return -ENOMEM; s->info = info; diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index f80f1af61ce7..967a4ed73929 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -336,7 +336,7 @@ static void raid1_end_read_request(struct bio *bio, int error) spin_lock_irqsave(&conf->device_lock, flags); if (r1_bio->mddev->degraded == conf->raid_disks || (r1_bio->mddev->degraded == conf->raid_disks-1 && - !test_bit(Faulty, &conf->mirrors[mirror].rdev->flags))) + test_bit(In_sync, &conf->mirrors[mirror].rdev->flags))) uptodate = 1; spin_unlock_irqrestore(&conf->device_lock, flags); } @@ -541,7 +541,7 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect if ((conf->mddev->recovery_cp < this_sector + sectors) || (mddev_is_clustered(conf->mddev) && - md_cluster_ops->area_resyncing(conf->mddev, this_sector, + md_cluster_ops->area_resyncing(conf->mddev, READ, this_sector, this_sector + sectors))) choose_first = 1; else @@ -1111,7 +1111,8 @@ static void make_request(struct mddev *mddev, struct bio * bio) ((bio_end_sector(bio) > mddev->suspend_lo && bio->bi_iter.bi_sector < mddev->suspend_hi) || (mddev_is_clustered(mddev) && - md_cluster_ops->area_resyncing(mddev, bio->bi_iter.bi_sector, bio_end_sector(bio))))) { + md_cluster_ops->area_resyncing(mddev, WRITE, + bio->bi_iter.bi_sector, bio_end_sector(bio))))) { /* As the suspend_* range is controlled by * userspace, we want an interruptible * wait. @@ -1124,7 +1125,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) if (bio_end_sector(bio) <= mddev->suspend_lo || bio->bi_iter.bi_sector >= mddev->suspend_hi || (mddev_is_clustered(mddev) && - !md_cluster_ops->area_resyncing(mddev, + !md_cluster_ops->area_resyncing(mddev, WRITE, bio->bi_iter.bi_sector, bio_end_sector(bio)))) break; schedule(); @@ -1475,6 +1476,7 @@ static void error(struct mddev *mddev, struct md_rdev *rdev) { char b[BDEVNAME_SIZE]; struct r1conf *conf = mddev->private; + unsigned long flags; /* * If it is not operational, then we have already marked it as dead @@ -1494,14 +1496,13 @@ static void error(struct mddev *mddev, struct md_rdev *rdev) return; } set_bit(Blocked, &rdev->flags); + spin_lock_irqsave(&conf->device_lock, flags); if (test_and_clear_bit(In_sync, &rdev->flags)) { - unsigned long flags; - spin_lock_irqsave(&conf->device_lock, flags); mddev->degraded++; set_bit(Faulty, &rdev->flags); - spin_unlock_irqrestore(&conf->device_lock, flags); } else set_bit(Faulty, &rdev->flags); + spin_unlock_irqrestore(&conf->device_lock, flags); /* * if recovery is running, make sure it aborts. */ @@ -1567,7 +1568,10 @@ static int raid1_spare_active(struct mddev *mddev) * Find all failed disks within the RAID1 configuration * and mark them readable. * Called under mddev lock, so rcu protection not needed. + * device_lock used to avoid races with raid1_end_read_request + * which expects 'In_sync' flags and ->degraded to be consistent. */ + spin_lock_irqsave(&conf->device_lock, flags); for (i = 0; i < conf->raid_disks; i++) { struct md_rdev *rdev = conf->mirrors[i].rdev; struct md_rdev *repl = conf->mirrors[conf->raid_disks + i].rdev; @@ -1598,7 +1602,6 @@ static int raid1_spare_active(struct mddev *mddev) sysfs_notify_dirent_safe(rdev->sysfs_state); } } - spin_lock_irqsave(&conf->device_lock, flags); mddev->degraded -= count; spin_unlock_irqrestore(&conf->device_lock, flags); diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 940f2f365461..38c58e19cfce 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -3556,6 +3556,7 @@ static struct r10conf *setup_conf(struct mddev *mddev) /* far_copies must be 1 */ conf->prev.stride = conf->dev_sectors; } + conf->reshape_safe = conf->reshape_progress; spin_lock_init(&conf->device_lock); INIT_LIST_HEAD(&conf->retry_list); @@ -3760,7 +3761,6 @@ static int run(struct mddev *mddev) } conf->offset_diff = min_offset_diff; - conf->reshape_safe = conf->reshape_progress; clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); @@ -4103,6 +4103,7 @@ static int raid10_start_reshape(struct mddev *mddev) conf->reshape_progress = size; } else conf->reshape_progress = 0; + conf->reshape_safe = conf->reshape_progress; spin_unlock_irq(&conf->device_lock); if (mddev->delta_disks && mddev->bitmap) { @@ -4170,6 +4171,7 @@ abort: rdev->new_data_offset = rdev->data_offset; smp_wmb(); conf->reshape_progress = MaxSector; + conf->reshape_safe = MaxSector; mddev->reshape_position = MaxSector; spin_unlock_irq(&conf->device_lock); return ret; @@ -4524,6 +4526,7 @@ static void end_reshape(struct r10conf *conf) md_finish_reshape(conf->mddev); smp_wmb(); conf->reshape_progress = MaxSector; + conf->reshape_safe = MaxSector; spin_unlock_irq(&conf->device_lock); /* read-ahead size must cover two whole stripes, which is diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 59e44e99eef3..f757023fc458 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2162,6 +2162,9 @@ static int resize_stripes(struct r5conf *conf, int newsize) if (!sc) return -ENOMEM; + /* Need to ensure auto-resizing doesn't interfere */ + mutex_lock(&conf->cache_size_mutex); + for (i = conf->max_nr_stripes; i; i--) { nsh = alloc_stripe(sc, GFP_KERNEL); if (!nsh) @@ -2178,6 +2181,7 @@ static int resize_stripes(struct r5conf *conf, int newsize) kmem_cache_free(sc, nsh); } kmem_cache_destroy(sc); + mutex_unlock(&conf->cache_size_mutex); return -ENOMEM; } /* Step 2 - Must use GFP_NOIO now. @@ -2224,6 +2228,7 @@ static int resize_stripes(struct r5conf *conf, int newsize) } else err = -ENOMEM; + mutex_unlock(&conf->cache_size_mutex); /* Step 4, return new stripes to service */ while(!list_empty(&newstripes)) { nsh = list_entry(newstripes.next, struct stripe_head, lru); @@ -2251,7 +2256,7 @@ static int resize_stripes(struct r5conf *conf, int newsize) static int drop_one_stripe(struct r5conf *conf) { struct stripe_head *sh; - int hash = (conf->max_nr_stripes - 1) % NR_STRIPE_HASH_LOCKS; + int hash = (conf->max_nr_stripes - 1) & STRIPE_HASH_LOCKS_MASK; spin_lock_irq(conf->hash_locks + hash); sh = get_free_stripe(conf, hash); @@ -4061,8 +4066,10 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s) &first_bad, &bad_sectors)) set_bit(R5_ReadRepl, &dev->flags); else { - if (rdev) + if (rdev && !test_bit(Faulty, &rdev->flags)) set_bit(R5_NeedReplace, &dev->flags); + else + clear_bit(R5_NeedReplace, &dev->flags); rdev = rcu_dereference(conf->disks[i].rdev); clear_bit(R5_ReadRepl, &dev->flags); } @@ -5857,12 +5864,14 @@ static void raid5d(struct md_thread *thread) pr_debug("%d stripes handled\n", handled); spin_unlock_irq(&conf->device_lock); - if (test_and_clear_bit(R5_ALLOC_MORE, &conf->cache_state)) { + if (test_and_clear_bit(R5_ALLOC_MORE, &conf->cache_state) && + mutex_trylock(&conf->cache_size_mutex)) { grow_one_stripe(conf, __GFP_NOWARN); /* Set flag even if allocation failed. This helps * slow down allocation requests when mem is short */ set_bit(R5_DID_ALLOC, &conf->cache_state); + mutex_unlock(&conf->cache_size_mutex); } async_tx_issue_pending_all(); @@ -5894,18 +5903,22 @@ raid5_set_cache_size(struct mddev *mddev, int size) return -EINVAL; conf->min_nr_stripes = size; + mutex_lock(&conf->cache_size_mutex); while (size < conf->max_nr_stripes && drop_one_stripe(conf)) ; + mutex_unlock(&conf->cache_size_mutex); err = md_allow_write(mddev); if (err) return err; + mutex_lock(&conf->cache_size_mutex); while (size > conf->max_nr_stripes) if (!grow_one_stripe(conf, GFP_KERNEL)) break; + mutex_unlock(&conf->cache_size_mutex); return 0; } @@ -6371,11 +6384,19 @@ static unsigned long raid5_cache_scan(struct shrinker *shrink, struct shrink_control *sc) { struct r5conf *conf = container_of(shrink, struct r5conf, shrinker); - int ret = 0; - while (ret < sc->nr_to_scan) { - if (drop_one_stripe(conf) == 0) - return SHRINK_STOP; - ret++; + unsigned long ret = SHRINK_STOP; + + if (mutex_trylock(&conf->cache_size_mutex)) { + ret= 0; + while (ret < sc->nr_to_scan && + conf->max_nr_stripes > conf->min_nr_stripes) { + if (drop_one_stripe(conf) == 0) { + ret = SHRINK_STOP; + break; + } + ret++; + } + mutex_unlock(&conf->cache_size_mutex); } return ret; } @@ -6444,6 +6465,7 @@ static struct r5conf *setup_conf(struct mddev *mddev) goto abort; spin_lock_init(&conf->device_lock); seqcount_init(&conf->gen_lock); + mutex_init(&conf->cache_size_mutex); init_waitqueue_head(&conf->wait_for_quiescent); for (i = 0; i < NR_STRIPE_HASH_LOCKS; i++) { init_waitqueue_head(&conf->wait_for_stripe[i]); diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h index 02c3bf8fbfe7..d05144278690 100644 --- a/drivers/md/raid5.h +++ b/drivers/md/raid5.h @@ -482,7 +482,8 @@ struct r5conf { */ int active_name; char cache_name[2][32]; - struct kmem_cache *slab_cache; /* for allocating stripes */ + struct kmem_cache *slab_cache; /* for allocating stripes */ + struct mutex cache_size_mutex; /* Protect changes to cache size */ int seq_flush, seq_write; int quiesce; diff --git a/drivers/media/pci/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c index 4cb365d4ffdc..8b95eefb610b 100644 --- a/drivers/media/pci/ivtv/ivtvfb.c +++ b/drivers/media/pci/ivtv/ivtvfb.c @@ -38,6 +38,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/kernel.h> #include <linux/fb.h> @@ -1171,6 +1173,13 @@ static int ivtvfb_init_card(struct ivtv *itv) { int rc; +#ifdef CONFIG_X86_64 + if (pat_enabled()) { + pr_warn("ivtvfb needs PAT disabled, boot with nopat kernel parameter\n"); + return -ENODEV; + } +#endif + if (itv->osd_info) { IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id); return -EBUSY; @@ -1265,12 +1274,6 @@ static int __init ivtvfb_init(void) int registered = 0; int err; -#ifdef CONFIG_X86_64 - if (WARN(pat_enabled(), - "ivtvfb needs PAT disabled, boot with nopat kernel parameter\n")) { - return -ENODEV; - } -#endif if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) { printk(KERN_ERR "ivtvfb: ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n", diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 8911e51d410a..3a27a84ad3ec 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -2074,14 +2074,8 @@ static int gpmc_probe_dt(struct platform_device *pdev) ret = gpmc_probe_nand_child(pdev, child); else if (of_node_cmp(child->name, "onenand") == 0) ret = gpmc_probe_onenand_child(pdev, child); - else if (of_node_cmp(child->name, "ethernet") == 0 || - of_node_cmp(child->name, "nor") == 0 || - of_node_cmp(child->name, "uart") == 0) + else ret = gpmc_probe_generic_child(pdev, child); - - if (WARN(ret < 0, "%s: probing gpmc child %s failed\n", - __func__, child->full_name)) - of_node_put(child); } return 0; diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c index 5c054031c3f8..e14c8c9d189b 100644 --- a/drivers/mfd/stmpe-i2c.c +++ b/drivers/mfd/stmpe-i2c.c @@ -6,7 +6,7 @@ * * License Terms: GNU General Public License, version 2 * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson - * Author: Viresh Kumar <viresh.linux@gmail.com> for ST Microelectronics + * Author: Viresh Kumar <vireshk@kernel.org> for ST Microelectronics */ #include <linux/i2c.h> diff --git a/drivers/mfd/stmpe-spi.c b/drivers/mfd/stmpe-spi.c index a81badbaa917..6fdb30e84a2b 100644 --- a/drivers/mfd/stmpe-spi.c +++ b/drivers/mfd/stmpe-spi.c @@ -4,7 +4,7 @@ * Copyright (C) ST Microelectronics SA 2011 * * License Terms: GNU General Public License, version 2 - * Author: Viresh Kumar <viresh.linux@gmail.com> for ST Microelectronics + * Author: Viresh Kumar <vireshk@kernel.org> for ST Microelectronics */ #include <linux/spi/spi.h> @@ -146,4 +146,4 @@ module_exit(stmpe_exit); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("STMPE MFD SPI Interface Driver"); -MODULE_AUTHOR("Viresh Kumar <viresh.linux@gmail.com>"); +MODULE_AUTHOR("Viresh Kumar <vireshk@kernel.org>"); diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c index 0c77240ae2fc..729e0851167d 100644 --- a/drivers/misc/cxl/api.c +++ b/drivers/misc/cxl/api.c @@ -23,6 +23,7 @@ struct cxl_context *cxl_dev_context_init(struct pci_dev *dev) afu = cxl_pci_to_afu(dev); + get_device(&afu->dev); ctx = cxl_context_alloc(); if (IS_ERR(ctx)) return ctx; @@ -31,6 +32,7 @@ struct cxl_context *cxl_dev_context_init(struct pci_dev *dev) rc = cxl_context_init(ctx, afu, false, NULL); if (rc) { kfree(ctx); + put_device(&afu->dev); return ERR_PTR(-ENOMEM); } cxl_assign_psn_space(ctx); @@ -60,6 +62,8 @@ int cxl_release_context(struct cxl_context *ctx) if (ctx->status != CLOSED) return -EBUSY; + put_device(&ctx->afu->dev); + cxl_context_free(ctx); return 0; @@ -159,7 +163,6 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed, } ctx->status = STARTED; - get_device(&ctx->afu->dev); out: mutex_unlock(&ctx->status_mutex); return rc; @@ -175,12 +178,7 @@ EXPORT_SYMBOL_GPL(cxl_process_element); /* Stop a context. Returns 0 on success, otherwise -Errno */ int cxl_stop_context(struct cxl_context *ctx) { - int rc; - - rc = __detach_context(ctx); - if (!rc) - put_device(&ctx->afu->dev); - return rc; + return __detach_context(ctx); } EXPORT_SYMBOL_GPL(cxl_stop_context); diff --git a/drivers/misc/cxl/context.c b/drivers/misc/cxl/context.c index 2a4c80ac322a..1287148629c0 100644 --- a/drivers/misc/cxl/context.c +++ b/drivers/misc/cxl/context.c @@ -113,11 +113,11 @@ static int cxl_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) if (ctx->afu->current_mode == CXL_MODE_DEDICATED) { area = ctx->afu->psn_phys; - if (offset > ctx->afu->adapter->ps_size) + if (offset >= ctx->afu->adapter->ps_size) return VM_FAULT_SIGBUS; } else { area = ctx->psn_phys; - if (offset > ctx->psn_size) + if (offset >= ctx->psn_size) return VM_FAULT_SIGBUS; } @@ -145,8 +145,16 @@ static const struct vm_operations_struct cxl_mmap_vmops = { */ int cxl_context_iomap(struct cxl_context *ctx, struct vm_area_struct *vma) { + u64 start = vma->vm_pgoff << PAGE_SHIFT; u64 len = vma->vm_end - vma->vm_start; - len = min(len, ctx->psn_size); + + if (ctx->afu->current_mode == CXL_MODE_DEDICATED) { + if (start + len > ctx->afu->adapter->ps_size) + return -EINVAL; + } else { + if (start + len > ctx->psn_size) + return -EINVAL; + } if (ctx->afu->current_mode != CXL_MODE_DEDICATED) { /* make sure there is a valid per process space for this AFU */ diff --git a/drivers/misc/cxl/main.c b/drivers/misc/cxl/main.c index 833348e2c9cb..4a164ab8b35a 100644 --- a/drivers/misc/cxl/main.c +++ b/drivers/misc/cxl/main.c @@ -73,7 +73,7 @@ static inline void cxl_slbia_core(struct mm_struct *mm) spin_lock(&adapter->afu_list_lock); for (slice = 0; slice < adapter->slices; slice++) { afu = adapter->afu[slice]; - if (!afu->enabled) + if (!afu || !afu->enabled) continue; rcu_read_lock(); idr_for_each_entry(&afu->contexts_idr, ctx, id) diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index c68ef5806dbe..32ad09705949 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c @@ -539,7 +539,7 @@ err: static void cxl_unmap_slice_regs(struct cxl_afu *afu) { - if (afu->p1n_mmio) + if (afu->p2n_mmio) iounmap(afu->p2n_mmio); if (afu->p1n_mmio) iounmap(afu->p1n_mmio); diff --git a/drivers/misc/cxl/vphb.c b/drivers/misc/cxl/vphb.c index b1d1983a84a5..2eba002b580b 100644 --- a/drivers/misc/cxl/vphb.c +++ b/drivers/misc/cxl/vphb.c @@ -112,9 +112,10 @@ static int cxl_pcie_config_info(struct pci_bus *bus, unsigned int devfn, unsigned long addr; phb = pci_bus_to_host(bus); - afu = (struct cxl_afu *)phb->private_data; if (phb == NULL) return PCIBIOS_DEVICE_NOT_FOUND; + afu = (struct cxl_afu *)phb->private_data; + if (cxl_pcie_cfg_record(bus->number, devfn) > afu->crs_num) return PCIBIOS_DEVICE_NOT_FOUND; if (offset >= (unsigned long)phb->cfg_data) diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index 2d3db81be099..6ded3dc36644 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -438,9 +438,6 @@ static ssize_t at24_bin_write(struct file *filp, struct kobject *kobj, { struct at24_data *at24; - if (unlikely(off >= attr->size)) - return -EFBIG; - at24 = dev_get_drvdata(container_of(kobj, struct device, kobj)); return at24_write(at24, buf, off, count); } diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 357b6ae4d207..458aa5a09c52 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -552,22 +552,6 @@ void mei_cl_bus_rx_event(struct mei_cl *cl) schedule_work(&device->event_work); } -void mei_cl_bus_remove_devices(struct mei_device *dev) -{ - struct mei_cl *cl, *next; - - mutex_lock(&dev->device_lock); - list_for_each_entry_safe(cl, next, &dev->device_list, device_link) { - if (cl->device) - mei_cl_remove_device(cl->device); - - list_del(&cl->device_link); - mei_cl_unlink(cl); - kfree(cl); - } - mutex_unlock(&dev->device_lock); -} - int __init mei_cl_bus_init(void) { return bus_register(&mei_cl_bus_type); diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 94514b2c7a50..00c3865ca3b1 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -333,8 +333,6 @@ void mei_stop(struct mei_device *dev) mei_nfc_host_exit(dev); - mei_cl_bus_remove_devices(dev); - mutex_lock(&dev->device_lock); mei_wd_stop(dev); diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 8eb0a9500a90..e9513d651cd3 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -682,7 +682,7 @@ int mei_register(struct mei_device *dev, struct device *parent) /* Fill in the data structures */ devno = MKDEV(MAJOR(mei_devt), dev->minor); cdev_init(&dev->cdev, &mei_fops); - dev->cdev.owner = mei_fops.owner; + dev->cdev.owner = parent->driver->owner; /* Add the device */ ret = cdev_add(&dev->cdev, devno, 1); diff --git a/drivers/misc/mei/nfc.c b/drivers/misc/mei/nfc.c index b983c4ecad38..290ef3037437 100644 --- a/drivers/misc/mei/nfc.c +++ b/drivers/misc/mei/nfc.c @@ -402,11 +402,12 @@ void mei_nfc_host_exit(struct mei_device *dev) cldev->priv_data = NULL; - mutex_lock(&dev->device_lock); /* Need to remove the device here * since mei_nfc_free will unlink the clients */ mei_cl_remove_device(cldev); + + mutex_lock(&dev->device_lock); mei_nfc_free(ndev); mutex_unlock(&dev->device_lock); } diff --git a/drivers/misc/mic/scif/scif_nodeqp.c b/drivers/misc/mic/scif/scif_nodeqp.c index 41e3bdb10061..6dfdae3452d6 100644 --- a/drivers/misc/mic/scif/scif_nodeqp.c +++ b/drivers/misc/mic/scif/scif_nodeqp.c @@ -357,7 +357,7 @@ static void scif_p2p_freesg(struct scatterlist *sg) } static struct scatterlist * -scif_p2p_setsg(void __iomem *va, int page_size, int page_cnt) +scif_p2p_setsg(phys_addr_t pa, int page_size, int page_cnt) { struct scatterlist *sg; struct page *page; @@ -368,16 +368,11 @@ scif_p2p_setsg(void __iomem *va, int page_size, int page_cnt) return NULL; sg_init_table(sg, page_cnt); for (i = 0; i < page_cnt; i++) { - page = vmalloc_to_page((void __force *)va); - if (!page) - goto p2p_sg_err; + page = pfn_to_page(pa >> PAGE_SHIFT); sg_set_page(&sg[i], page, page_size, 0); - va += page_size; + pa += page_size; } return sg; -p2p_sg_err: - kfree(sg); - return NULL; } /* Init p2p mappings required to access peerdev from scifdev */ @@ -395,14 +390,14 @@ scif_init_p2p_info(struct scif_dev *scifdev, struct scif_dev *peerdev) p2p = kzalloc(sizeof(*p2p), GFP_KERNEL); if (!p2p) return NULL; - p2p->ppi_sg[SCIF_PPI_MMIO] = scif_p2p_setsg(psdev->mmio->va, + p2p->ppi_sg[SCIF_PPI_MMIO] = scif_p2p_setsg(psdev->mmio->pa, PAGE_SIZE, num_mmio_pages); if (!p2p->ppi_sg[SCIF_PPI_MMIO]) goto free_p2p; p2p->sg_nentries[SCIF_PPI_MMIO] = num_mmio_pages; sg_page_shift = get_order(min(psdev->aper->len, (u64)(1 << 30))); num_aper_chunks = num_aper_pages >> (sg_page_shift - PAGE_SHIFT); - p2p->ppi_sg[SCIF_PPI_APER] = scif_p2p_setsg(psdev->aper->va, + p2p->ppi_sg[SCIF_PPI_APER] = scif_p2p_setsg(psdev->aper->pa, 1 << sg_page_shift, num_aper_chunks); p2p->sg_nentries[SCIF_PPI_APER] = num_aper_chunks; diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index c9c3d20b784b..a1b820fcb2a6 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -208,6 +208,8 @@ static ssize_t power_ro_lock_show(struct device *dev, ret = snprintf(buf, PAGE_SIZE, "%d\n", locked); + mmc_blk_put(md); + return ret; } diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index fd9a58e216a5..6a0f9c79be26 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -779,6 +779,7 @@ config MMC_TOSHIBA_PCI config MMC_MTK tristate "MediaTek SD/MMC Card Interface support" + depends on HAS_DMA help This selects the MediaTek(R) Secure digital and Multimedia card Interface. If you have a machine with a integrated SD/MMC card reader, say Y or M here. diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index b2b411da297b..4d1203236890 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1062,9 +1062,14 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) if (status & (CTO_EN | CCRC_EN)) end_cmd = 1; + if (host->data || host->response_busy) { + end_trans = !end_cmd; + host->response_busy = 0; + } if (status & (CTO_EN | DTO_EN)) hsmmc_command_incomplete(host, -ETIMEDOUT, end_cmd); - else if (status & (CCRC_EN | DCRC_EN)) + else if (status & (CCRC_EN | DCRC_EN | DEB_EN | CEB_EN | + BADA_EN)) hsmmc_command_incomplete(host, -EILSEQ, end_cmd); if (status & ACE_EN) { @@ -1081,10 +1086,6 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) } dev_dbg(mmc_dev(host->mmc), "AC12 err: 0x%x\n", ac12); } - if (host->data || host->response_busy) { - end_trans = !end_cmd; - host->response_busy = 0; - } } OMAP_HSMMC_WRITE(host->base, STAT, status); diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index faf0cb910c96..c6b9f6492e1a 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -581,13 +581,8 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct pltfm_imx_data *imx_data = pltfm_host->priv; - struct esdhc_platform_data *boarddata = &imx_data->boarddata; - if (boarddata->f_max && (boarddata->f_max < pltfm_host->clock)) - return boarddata->f_max; - else - return pltfm_host->clock; + return pltfm_host->clock; } static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host) @@ -878,34 +873,19 @@ static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { static int sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, struct sdhci_host *host, - struct esdhc_platform_data *boarddata) + struct pltfm_imx_data *imx_data) { struct device_node *np = pdev->dev.of_node; - - if (!np) - return -ENODEV; - - if (of_get_property(np, "non-removable", NULL)) - boarddata->cd_type = ESDHC_CD_PERMANENT; - - if (of_get_property(np, "fsl,cd-controller", NULL)) - boarddata->cd_type = ESDHC_CD_CONTROLLER; + struct esdhc_platform_data *boarddata = &imx_data->boarddata; + int ret; if (of_get_property(np, "fsl,wp-controller", NULL)) boarddata->wp_type = ESDHC_WP_CONTROLLER; - boarddata->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0); - if (gpio_is_valid(boarddata->cd_gpio)) - boarddata->cd_type = ESDHC_CD_GPIO; - boarddata->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0); if (gpio_is_valid(boarddata->wp_gpio)) boarddata->wp_type = ESDHC_WP_GPIO; - of_property_read_u32(np, "bus-width", &boarddata->max_bus_width); - - of_property_read_u32(np, "max-frequency", &boarddata->f_max); - if (of_find_property(np, "no-1-8-v", NULL)) boarddata->support_vsel = false; else @@ -916,29 +896,119 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, mmc_of_parse_voltage(np, &host->ocr_mask); + /* sdr50 and sdr104 needs work on 1.8v signal voltage */ + if ((boarddata->support_vsel) && esdhc_is_usdhc(imx_data) && + !IS_ERR(imx_data->pins_default)) { + imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl, + ESDHC_PINCTRL_STATE_100MHZ); + imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl, + ESDHC_PINCTRL_STATE_200MHZ); + if (IS_ERR(imx_data->pins_100mhz) || + IS_ERR(imx_data->pins_200mhz)) { + dev_warn(mmc_dev(host->mmc), + "could not get ultra high speed state, work on normal mode\n"); + /* + * fall back to not support uhs by specify no 1.8v quirk + */ + host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; + } + } else { + host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; + } + /* call to generic mmc_of_parse to support additional capabilities */ - return mmc_of_parse(host->mmc); + ret = mmc_of_parse(host->mmc); + if (ret) + return ret; + + if (!IS_ERR_VALUE(mmc_gpio_get_cd(host->mmc))) + host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; + + return 0; } #else static inline int sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, struct sdhci_host *host, - struct esdhc_platform_data *boarddata) + struct pltfm_imx_data *imx_data) { return -ENODEV; } #endif +static int sdhci_esdhc_imx_probe_nondt(struct platform_device *pdev, + struct sdhci_host *host, + struct pltfm_imx_data *imx_data) +{ + struct esdhc_platform_data *boarddata = &imx_data->boarddata; + int err; + + if (!host->mmc->parent->platform_data) { + dev_err(mmc_dev(host->mmc), "no board data!\n"); + return -EINVAL; + } + + imx_data->boarddata = *((struct esdhc_platform_data *) + host->mmc->parent->platform_data); + /* write_protect */ + if (boarddata->wp_type == ESDHC_WP_GPIO) { + err = mmc_gpio_request_ro(host->mmc, boarddata->wp_gpio); + if (err) { + dev_err(mmc_dev(host->mmc), + "failed to request write-protect gpio!\n"); + return err; + } + host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; + } + + /* card_detect */ + switch (boarddata->cd_type) { + case ESDHC_CD_GPIO: + err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio, 0); + if (err) { + dev_err(mmc_dev(host->mmc), + "failed to request card-detect gpio!\n"); + return err; + } + /* fall through */ + + case ESDHC_CD_CONTROLLER: + /* we have a working card_detect back */ + host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; + break; + + case ESDHC_CD_PERMANENT: + host->mmc->caps |= MMC_CAP_NONREMOVABLE; + break; + + case ESDHC_CD_NONE: + break; + } + + switch (boarddata->max_bus_width) { + case 8: + host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA; + break; + case 4: + host->mmc->caps |= MMC_CAP_4_BIT_DATA; + break; + case 1: + default: + host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; + break; + } + + return 0; +} + static int sdhci_esdhc_imx_probe(struct platform_device *pdev) { const struct of_device_id *of_id = of_match_device(imx_esdhc_dt_ids, &pdev->dev); struct sdhci_pltfm_host *pltfm_host; struct sdhci_host *host; - struct esdhc_platform_data *boarddata; int err; struct pltfm_imx_data *imx_data; - bool dt = true; host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata, 0); if (IS_ERR(host)) @@ -1030,84 +1100,12 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536) host->quirks |= SDHCI_QUIRK_BROKEN_ADMA; - boarddata = &imx_data->boarddata; - if (sdhci_esdhc_imx_probe_dt(pdev, host, boarddata) < 0) { - if (!host->mmc->parent->platform_data) { - dev_err(mmc_dev(host->mmc), "no board data!\n"); - err = -EINVAL; - goto disable_clk; - } - imx_data->boarddata = *((struct esdhc_platform_data *) - host->mmc->parent->platform_data); - dt = false; - } - /* write_protect */ - if (boarddata->wp_type == ESDHC_WP_GPIO && !dt) { - err = mmc_gpio_request_ro(host->mmc, boarddata->wp_gpio); - if (err) { - dev_err(mmc_dev(host->mmc), - "failed to request write-protect gpio!\n"); - goto disable_clk; - } - host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; - } - - /* card_detect */ - switch (boarddata->cd_type) { - case ESDHC_CD_GPIO: - if (dt) - break; - err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio, 0); - if (err) { - dev_err(mmc_dev(host->mmc), - "failed to request card-detect gpio!\n"); - goto disable_clk; - } - /* fall through */ - - case ESDHC_CD_CONTROLLER: - /* we have a working card_detect back */ - host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; - break; - - case ESDHC_CD_PERMANENT: - host->mmc->caps |= MMC_CAP_NONREMOVABLE; - break; - - case ESDHC_CD_NONE: - break; - } - - switch (boarddata->max_bus_width) { - case 8: - host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA; - break; - case 4: - host->mmc->caps |= MMC_CAP_4_BIT_DATA; - break; - case 1: - default: - host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; - break; - } - - /* sdr50 and sdr104 needs work on 1.8v signal voltage */ - if ((boarddata->support_vsel) && esdhc_is_usdhc(imx_data) && - !IS_ERR(imx_data->pins_default)) { - imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl, - ESDHC_PINCTRL_STATE_100MHZ); - imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl, - ESDHC_PINCTRL_STATE_200MHZ); - if (IS_ERR(imx_data->pins_100mhz) || - IS_ERR(imx_data->pins_200mhz)) { - dev_warn(mmc_dev(host->mmc), - "could not get ultra high speed state, work on normal mode\n"); - /* fall back to not support uhs by specify no 1.8v quirk */ - host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; - } - } else { - host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V; - } + if (of_id) + err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data); + else + err = sdhci_esdhc_imx_probe_nondt(pdev, host, imx_data); + if (err) + goto disable_clk; err = sdhci_add_host(host); if (err) diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h index 3497cfaf683c..a870c42731d7 100644 --- a/drivers/mmc/host/sdhci-esdhc.h +++ b/drivers/mmc/host/sdhci-esdhc.h @@ -45,6 +45,6 @@ #define ESDHC_DMA_SYSCTL 0x40c #define ESDHC_DMA_SNOOP 0x00000040 -#define ESDHC_HOST_CONTROL_RES 0x05 +#define ESDHC_HOST_CONTROL_RES 0x01 #endif /* _DRIVERS_MMC_SDHCI_ESDHC_H */ diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index 9cd5fc62f130..946d37f94a31 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -411,6 +411,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) goto err_of_parse; sdhci_get_of_property(pdev); pdata = pxav3_get_mmc_pdata(dev); + pdev->dev.platform_data = pdata; } else if (pdata) { /* on-chip device */ if (pdata->flags & PXA_FLAG_CARD_PERMANENT) diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c index df088343d60f..255a896769b8 100644 --- a/drivers/mmc/host/sdhci-spear.c +++ b/drivers/mmc/host/sdhci-spear.c @@ -4,7 +4,7 @@ * Support of SDHCI platform devices for spear soc family * * Copyright (C) 2010 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * Inspired by sdhci-pltfm.c * @@ -211,5 +211,5 @@ static struct platform_driver sdhci_driver = { module_platform_driver(sdhci_driver); MODULE_DESCRIPTION("SPEAr Secure Digital Host Controller Interface driver"); -MODULE_AUTHOR("Viresh Kumar <viresh.linux@gmail.com>"); +MODULE_AUTHOR("Viresh Kumar <vireshk@kernel.org>"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index bc1445238fb3..1dbe93232030 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2866,6 +2866,7 @@ int sdhci_add_host(struct sdhci_host *host) u32 max_current_caps; unsigned int ocr_avail; unsigned int override_timeout_clk; + u32 max_clk; int ret; WARN_ON(host == NULL); @@ -2978,8 +2979,11 @@ int sdhci_add_host(struct sdhci_host *host) GFP_KERNEL); host->align_buffer = kmalloc(host->align_buffer_sz, GFP_KERNEL); if (!host->adma_table || !host->align_buffer) { - dma_free_coherent(mmc_dev(mmc), host->adma_table_sz, - host->adma_table, host->adma_addr); + if (host->adma_table) + dma_free_coherent(mmc_dev(mmc), + host->adma_table_sz, + host->adma_table, + host->adma_addr); kfree(host->align_buffer); pr_warn("%s: Unable to allocate ADMA buffers - falling back to standard DMA\n", mmc_hostname(mmc)); @@ -3047,18 +3051,22 @@ int sdhci_add_host(struct sdhci_host *host) * Set host parameters. */ mmc->ops = &sdhci_ops; - mmc->f_max = host->max_clk; + max_clk = host->max_clk; + if (host->ops->get_min_clock) mmc->f_min = host->ops->get_min_clock(host); else if (host->version >= SDHCI_SPEC_300) { if (host->clk_mul) { mmc->f_min = (host->max_clk * host->clk_mul) / 1024; - mmc->f_max = host->max_clk * host->clk_mul; + max_clk = host->max_clk * host->clk_mul; } else mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300; } else mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; + if (!mmc->f_max || (mmc->f_max && (mmc->f_max > max_clk))) + mmc->f_max = max_clk; + if (!(host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) { host->timeout_clk = (caps[0] & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 19eb990d398c..e1ccefce9a9d 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -625,6 +625,23 @@ static void bond_set_dev_addr(struct net_device *bond_dev, call_netdevice_notifiers(NETDEV_CHANGEADDR, bond_dev); } +static struct slave *bond_get_old_active(struct bonding *bond, + struct slave *new_active) +{ + struct slave *slave; + struct list_head *iter; + + bond_for_each_slave(bond, slave, iter) { + if (slave == new_active) + continue; + + if (ether_addr_equal(bond->dev->dev_addr, slave->dev->dev_addr)) + return slave; + } + + return NULL; +} + /* bond_do_fail_over_mac * * Perform special MAC address swapping for fail_over_mac settings @@ -652,6 +669,9 @@ static void bond_do_fail_over_mac(struct bonding *bond, if (!new_active) return; + if (!old_active) + old_active = bond_get_old_active(bond, new_active); + if (old_active) { ether_addr_copy(tmp_mac, new_active->dev->dev_addr); ether_addr_copy(saddr.sa_data, @@ -689,40 +709,57 @@ out: } -static bool bond_should_change_active(struct bonding *bond) +static struct slave *bond_choose_primary_or_current(struct bonding *bond) { struct slave *prim = rtnl_dereference(bond->primary_slave); struct slave *curr = rtnl_dereference(bond->curr_active_slave); - if (!prim || !curr || curr->link != BOND_LINK_UP) - return true; + if (!prim || prim->link != BOND_LINK_UP) { + if (!curr || curr->link != BOND_LINK_UP) + return NULL; + return curr; + } + if (bond->force_primary) { bond->force_primary = false; - return true; + return prim; + } + + if (!curr || curr->link != BOND_LINK_UP) + return prim; + + /* At this point, prim and curr are both up */ + switch (bond->params.primary_reselect) { + case BOND_PRI_RESELECT_ALWAYS: + return prim; + case BOND_PRI_RESELECT_BETTER: + if (prim->speed < curr->speed) + return curr; + if (prim->speed == curr->speed && prim->duplex <= curr->duplex) + return curr; + return prim; + case BOND_PRI_RESELECT_FAILURE: + return curr; + default: + netdev_err(bond->dev, "impossible primary_reselect %d\n", + bond->params.primary_reselect); + return curr; } - if (bond->params.primary_reselect == BOND_PRI_RESELECT_BETTER && - (prim->speed < curr->speed || - (prim->speed == curr->speed && prim->duplex <= curr->duplex))) - return false; - if (bond->params.primary_reselect == BOND_PRI_RESELECT_FAILURE) - return false; - return true; } /** - * find_best_interface - select the best available slave to be the active one + * bond_find_best_slave - select the best available slave to be the active one * @bond: our bonding struct */ static struct slave *bond_find_best_slave(struct bonding *bond) { - struct slave *slave, *bestslave = NULL, *primary; + struct slave *slave, *bestslave = NULL; struct list_head *iter; int mintime = bond->params.updelay; - primary = rtnl_dereference(bond->primary_slave); - if (primary && primary->link == BOND_LINK_UP && - bond_should_change_active(bond)) - return primary; + slave = bond_choose_primary_or_current(bond); + if (slave) + return slave; bond_for_each_slave(bond, slave, iter) { if (slave->link == BOND_LINK_UP) @@ -1708,9 +1745,16 @@ err_free: err_undo_flags: /* Enslave of first slave has failed and we need to fix master's mac */ - if (!bond_has_slaves(bond) && - ether_addr_equal_64bits(bond_dev->dev_addr, slave_dev->dev_addr)) - eth_hw_addr_random(bond_dev); + if (!bond_has_slaves(bond)) { + if (ether_addr_equal_64bits(bond_dev->dev_addr, + slave_dev->dev_addr)) + eth_hw_addr_random(bond_dev); + if (bond_dev->type != ARPHRD_ETHER) { + ether_setup(bond_dev); + bond_dev->flags |= IFF_MASTER; + bond_dev->priv_flags &= ~IFF_TX_SKB_SHARING; + } + } return res; } @@ -1899,6 +1943,7 @@ static int bond_release_and_destroy(struct net_device *bond_dev, bond_dev->priv_flags |= IFF_DISABLE_NETPOLL; netdev_info(bond_dev, "Destroying bond %s\n", bond_dev->name); + bond_remove_proc_entry(bond); unregister_netdevice(bond_dev); } return ret; diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index f4e40aa4d2a2..945c0955a967 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -577,10 +577,10 @@ static void at91_rx_overflow_err(struct net_device *dev) cf->can_id |= CAN_ERR_CRTL; cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; - netif_receive_skb(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_receive_skb(skb); } /** @@ -642,10 +642,10 @@ static void at91_read_msg(struct net_device *dev, unsigned int mb) } at91_read_mb(dev, mb, cf); - netif_receive_skb(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_receive_skb(skb); can_led_event(dev, CAN_LED_EVENT_RX); } @@ -802,10 +802,10 @@ static int at91_poll_err(struct net_device *dev, int quota, u32 reg_sr) return 0; at91_poll_err_frame(dev, cf, reg_sr); - netif_receive_skb(skb); dev->stats.rx_packets++; dev->stats.rx_bytes += cf->can_dlc; + netif_receive_skb(skb); return 1; } @@ -1067,10 +1067,10 @@ static void at91_irq_err(struct net_device *dev) return; at91_irq_err_state(dev, cf, new_state); - netif_rx(skb); dev->stats.rx_packets++; dev->stats.rx_bytes += cf->can_dlc; + netif_rx(skb); priv->can.state = new_state; } diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c index 27ad312e7abf..57dadd52b428 100644 --- a/drivers/net/can/bfin_can.c +++ b/drivers/net/can/bfin_can.c @@ -424,10 +424,9 @@ static void bfin_can_rx(struct net_device *dev, u16 isrc) cf->data[6 - i] = (6 - i) < cf->can_dlc ? (val >> 8) : 0; } - netif_rx(skb); - stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); } static int bfin_can_err(struct net_device *dev, u16 isrc, u16 status) @@ -508,10 +507,9 @@ static int bfin_can_err(struct net_device *dev, u16 isrc, u16 status) priv->can.state = state; - netif_rx(skb); - stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); return 0; } diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 041525d2595c..5d214d135332 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -592,6 +592,7 @@ static int c_can_start(struct net_device *dev) { struct c_can_priv *priv = netdev_priv(dev); int err; + struct pinctrl *p; /* basic c_can configuration */ err = c_can_chip_config(dev); @@ -604,8 +605,13 @@ static int c_can_start(struct net_device *dev) priv->can.state = CAN_STATE_ERROR_ACTIVE; - /* activate pins */ - pinctrl_pm_select_default_state(dev->dev.parent); + /* Attempt to use "active" if available else use "default" */ + p = pinctrl_get_select(priv->device, "active"); + if (!IS_ERR(p)) + pinctrl_put(p); + else + pinctrl_pm_select_default_state(priv->device); + return 0; } diff --git a/drivers/net/can/cc770/cc770.c b/drivers/net/can/cc770/cc770.c index c11d44984036..70a8cbb29e75 100644 --- a/drivers/net/can/cc770/cc770.c +++ b/drivers/net/can/cc770/cc770.c @@ -504,10 +504,10 @@ static void cc770_rx(struct net_device *dev, unsigned int mo, u8 ctrl1) for (i = 0; i < cf->can_dlc; i++) cf->data[i] = cc770_read_reg(priv, msgobj[mo].data[i]); } - netif_rx(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); } static int cc770_err(struct net_device *dev, u8 status) @@ -584,10 +584,10 @@ static int cc770_err(struct net_device *dev, u8 status) } } - netif_rx(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); return 0; } diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index e9b1810d319f..aede704605c6 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -440,9 +440,6 @@ unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx) struct can_frame *cf = (struct can_frame *)skb->data; u8 dlc = cf->can_dlc; - if (!(skb->tstamp.tv64)) - __net_timestamp(skb); - netif_rx(priv->echo_skb[idx]); priv->echo_skb[idx] = NULL; @@ -578,7 +575,6 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf) if (unlikely(!skb)) return NULL; - __net_timestamp(skb); skb->protocol = htons(ETH_P_CAN); skb->pkt_type = PACKET_BROADCAST; skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -589,6 +585,7 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf) can_skb_reserve(skb); can_skb_prv(skb)->ifindex = dev->ifindex; + can_skb_prv(skb)->skbcnt = 0; *cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); memset(*cf, 0, sizeof(struct can_frame)); @@ -607,7 +604,6 @@ struct sk_buff *alloc_canfd_skb(struct net_device *dev, if (unlikely(!skb)) return NULL; - __net_timestamp(skb); skb->protocol = htons(ETH_P_CANFD); skb->pkt_type = PACKET_BROADCAST; skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -618,6 +614,7 @@ struct sk_buff *alloc_canfd_skb(struct net_device *dev, can_skb_reserve(skb); can_skb_prv(skb)->ifindex = dev->ifindex; + can_skb_prv(skb)->skbcnt = 0; *cfd = (struct canfd_frame *)skb_put(skb, sizeof(struct canfd_frame)); memset(*cfd, 0, sizeof(struct canfd_frame)); diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 6201c5a1a884..b1e8d729851c 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -577,10 +577,10 @@ static int flexcan_poll_bus_err(struct net_device *dev, u32 reg_esr) return 0; do_bus_err(dev, cf, reg_esr); - netif_receive_skb(skb); dev->stats.rx_packets++; dev->stats.rx_bytes += cf->can_dlc; + netif_receive_skb(skb); return 1; } @@ -622,10 +622,9 @@ static int flexcan_poll_state(struct net_device *dev, u32 reg_esr) if (unlikely(new_state == CAN_STATE_BUS_OFF)) can_bus_off(dev); - netif_receive_skb(skb); - dev->stats.rx_packets++; dev->stats.rx_bytes += cf->can_dlc; + netif_receive_skb(skb); return 1; } @@ -670,10 +669,10 @@ static int flexcan_read_frame(struct net_device *dev) } flexcan_read_fifo(dev, cf); - netif_receive_skb(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_receive_skb(skb); can_led_event(dev, CAN_LED_EVENT_RX); diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c index e3d7e22a4fa0..db9538d4b358 100644 --- a/drivers/net/can/grcan.c +++ b/drivers/net/can/grcan.c @@ -1216,11 +1216,12 @@ static int grcan_receive(struct net_device *dev, int budget) cf->data[i] = (u8)(slot[j] >> shift); } } - netif_receive_skb(skb); /* Update statistics and read pointer */ stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_receive_skb(skb); + rd = grcan_ring_add(rd, GRCAN_MSG_SIZE, dma->rx.size); } diff --git a/drivers/net/can/rcar_can.c b/drivers/net/can/rcar_can.c index 7deb80dcbe8c..7bd54191f962 100644 --- a/drivers/net/can/rcar_can.c +++ b/drivers/net/can/rcar_can.c @@ -508,7 +508,8 @@ static int rcar_can_open(struct net_device *ndev) err = clk_prepare_enable(priv->clk); if (err) { - netdev_err(ndev, "failed to enable periperal clock, error %d\n", + netdev_err(ndev, + "failed to enable peripheral clock, error %d\n", err); goto out; } @@ -526,7 +527,8 @@ static int rcar_can_open(struct net_device *ndev) napi_enable(&priv->napi); err = request_irq(ndev->irq, rcar_can_interrupt, 0, ndev->name, ndev); if (err) { - netdev_err(ndev, "error requesting interrupt %x\n", ndev->irq); + netdev_err(ndev, "request_irq(%d) failed, error %d\n", + ndev->irq, err); goto out_close; } can_led_event(ndev, CAN_LED_EVENT_OPEN); @@ -758,8 +760,9 @@ static int rcar_can_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (!irq) { + if (irq < 0) { dev_err(&pdev->dev, "No IRQ resource\n"); + err = irq; goto fail; } @@ -782,7 +785,8 @@ static int rcar_can_probe(struct platform_device *pdev) priv->clk = devm_clk_get(&pdev->dev, "clkp1"); if (IS_ERR(priv->clk)) { err = PTR_ERR(priv->clk); - dev_err(&pdev->dev, "cannot get peripheral clock: %d\n", err); + dev_err(&pdev->dev, "cannot get peripheral clock, error %d\n", + err); goto fail_clk; } @@ -794,7 +798,7 @@ static int rcar_can_probe(struct platform_device *pdev) priv->can_clk = devm_clk_get(&pdev->dev, clock_names[clock_select]); if (IS_ERR(priv->can_clk)) { err = PTR_ERR(priv->can_clk); - dev_err(&pdev->dev, "cannot get CAN clock: %d\n", err); + dev_err(&pdev->dev, "cannot get CAN clock, error %d\n", err); goto fail_clk; } @@ -823,7 +827,7 @@ static int rcar_can_probe(struct platform_device *pdev) devm_can_led_init(ndev); - dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%u)\n", + dev_info(&pdev->dev, "device registered (regs @ %p, IRQ%d)\n", priv->regs, ndev->irq); return 0; diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 32bd7f451aa4..7b92e911a616 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -377,10 +377,9 @@ static void sja1000_rx(struct net_device *dev) /* release receive buffer */ sja1000_write_cmdreg(priv, CMD_RRB); - netif_rx(skb); - stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); can_led_event(dev, CAN_LED_EVENT_RX); } @@ -484,10 +483,9 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) can_bus_off(dev); } - netif_rx(skb); - stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); return 0; } diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index f64f5290d6f8..9a3f15cb7ef4 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c @@ -207,7 +207,6 @@ static void slc_bump(struct slcan *sl) if (!skb) return; - __net_timestamp(skb); skb->dev = sl->dev; skb->protocol = htons(ETH_P_CAN); skb->pkt_type = PACKET_BROADCAST; @@ -215,13 +214,14 @@ static void slc_bump(struct slcan *sl) can_skb_reserve(skb); can_skb_prv(skb)->ifindex = sl->dev->ifindex; + can_skb_prv(skb)->skbcnt = 0; memcpy(skb_put(skb, sizeof(struct can_frame)), &cf, sizeof(struct can_frame)); - netif_rx_ni(skb); sl->dev->stats.rx_packets++; sl->dev->stats.rx_bytes += cf.can_dlc; + netif_rx_ni(skb); } /* parse tty input stream */ diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c index c1a95a34d62e..b7e83c212023 100644 --- a/drivers/net/can/spi/mcp251x.c +++ b/drivers/net/can/spi/mcp251x.c @@ -1086,8 +1086,8 @@ static int mcp251x_can_probe(struct spi_device *spi) if (ret) goto out_clk; - priv->power = devm_regulator_get(&spi->dev, "vdd"); - priv->transceiver = devm_regulator_get(&spi->dev, "xceiver"); + priv->power = devm_regulator_get_optional(&spi->dev, "vdd"); + priv->transceiver = devm_regulator_get_optional(&spi->dev, "xceiver"); if ((PTR_ERR(priv->power) == -EPROBE_DEFER) || (PTR_ERR(priv->transceiver) == -EPROBE_DEFER)) { ret = -EPROBE_DEFER; @@ -1222,17 +1222,16 @@ static int __maybe_unused mcp251x_can_resume(struct device *dev) struct spi_device *spi = to_spi_device(dev); struct mcp251x_priv *priv = spi_get_drvdata(spi); - if (priv->after_suspend & AFTER_SUSPEND_POWER) { + if (priv->after_suspend & AFTER_SUSPEND_POWER) mcp251x_power_enable(priv->power, 1); + + if (priv->after_suspend & AFTER_SUSPEND_UP) { + mcp251x_power_enable(priv->transceiver, 1); queue_work(priv->wq, &priv->restart_work); } else { - if (priv->after_suspend & AFTER_SUSPEND_UP) { - mcp251x_power_enable(priv->transceiver, 1); - queue_work(priv->wq, &priv->restart_work); - } else { - priv->after_suspend = 0; - } + priv->after_suspend = 0; } + priv->force_quit = 0; enable_irq(spi->irq); return 0; diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index e95a9e1a889f..cf345cbfe819 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -747,9 +747,9 @@ static int ti_hecc_error(struct net_device *ndev, int int_status, } } - netif_rx(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); return 0; } diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index 866bac0ae7e9..2d390384ef3b 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -324,10 +324,9 @@ static void ems_usb_rx_can_msg(struct ems_usb *dev, struct ems_cpc_msg *msg) cf->data[i] = msg->msg.can_msg.msg[i]; } - netif_rx(skb); - stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); } static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg) @@ -400,10 +399,9 @@ static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg) stats->rx_errors++; } - netif_rx(skb); - stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); } /* diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c index 411c1af92c62..0e5a4493ba4f 100644 --- a/drivers/net/can/usb/esd_usb2.c +++ b/drivers/net/can/usb/esd_usb2.c @@ -301,13 +301,12 @@ static void esd_usb2_rx_event(struct esd_usb2_net_priv *priv, cf->data[7] = rxerr; } - netif_rx(skb); - priv->bec.txerr = txerr; priv->bec.rxerr = rxerr; stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); } } @@ -347,10 +346,9 @@ static void esd_usb2_rx_can_msg(struct esd_usb2_net_priv *priv, cf->data[i] = msg->msg.rx.data[i]; } - netif_rx(skb); - stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); } return; diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c index 72427f21edff..6b94007ae052 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb.c @@ -526,9 +526,9 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n, hwts->hwtstamp = timeval_to_ktime(tv); } - netif_rx(skb); mc->netdev->stats.rx_packets++; mc->netdev->stats.rx_bytes += cf->can_dlc; + netif_rx(skb); return 0; } @@ -659,12 +659,11 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len) hwts = skb_hwtstamps(skb); hwts->hwtstamp = timeval_to_ktime(tv); - /* push the skb */ - netif_rx(skb); - /* update statistics */ mc->netdev->stats.rx_packets++; mc->netdev->stats.rx_bytes += cf->can_dlc; + /* push the skb */ + netif_rx(skb); return 0; diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c index dec51717635e..7d61b3279798 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c @@ -553,9 +553,9 @@ static int pcan_usb_pro_handle_canmsg(struct pcan_usb_pro_interface *usb_if, hwts = skb_hwtstamps(skb); hwts->hwtstamp = timeval_to_ktime(tv); - netif_rx(skb); netdev->stats.rx_packets++; netdev->stats.rx_bytes += can_frame->can_dlc; + netif_rx(skb); return 0; } @@ -670,9 +670,9 @@ static int pcan_usb_pro_handle_error(struct pcan_usb_pro_interface *usb_if, peak_usb_get_ts_tv(&usb_if->time_ref, le32_to_cpu(er->ts32), &tv); hwts = skb_hwtstamps(skb); hwts->hwtstamp = timeval_to_ktime(tv); - netif_rx(skb); netdev->stats.rx_packets++; netdev->stats.rx_bytes += can_frame->can_dlc; + netif_rx(skb); return 0; } diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c index dd52c7a4c80d..de95b1ccba3e 100644 --- a/drivers/net/can/usb/usb_8dev.c +++ b/drivers/net/can/usb/usb_8dev.c @@ -461,10 +461,9 @@ static void usb_8dev_rx_err_msg(struct usb_8dev_priv *priv, priv->bec.txerr = txerr; priv->bec.rxerr = rxerr; - netif_rx(skb); - stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); } /* Read data and status frames */ @@ -494,10 +493,9 @@ static void usb_8dev_rx_can_msg(struct usb_8dev_priv *priv, else memcpy(cf->data, msg->data, cf->can_dlc); - netif_rx(skb); - stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx(skb); can_led_event(priv->netdev, CAN_LED_EVENT_RX); } else { diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c index 0ce868de855d..674f367087c5 100644 --- a/drivers/net/can/vcan.c +++ b/drivers/net/can/vcan.c @@ -78,9 +78,6 @@ static void vcan_rx(struct sk_buff *skb, struct net_device *dev) skb->dev = dev; skb->ip_summed = CHECKSUM_UNNECESSARY; - if (!(skb->tstamp.tv64)) - __net_timestamp(skb); - netif_rx_ni(skb); } diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 972982f8bea7..079897b3a955 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -696,9 +696,20 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds) } /* Include the pseudo-PHY address and the broadcast PHY address to - * divert reads towards our workaround + * divert reads towards our workaround. This is only required for + * 7445D0, since 7445E0 disconnects the internal switch pseudo-PHY such + * that we can use the regular SWITCH_MDIO master controller instead. + * + * By default, DSA initializes ds->phys_mii_mask to ds->phys_port_mask + * to have a 1:1 mapping between Port address and PHY address in order + * to utilize the slave_mii_bus instance to read from Port PHYs. This is + * not what we want here, so we initialize phys_mii_mask 0 to always + * utilize the "master" MDIO bus backed by the "mdio-unimac" driver. */ - ds->phys_mii_mask |= ((1 << BRCM_PSEUDO_PHY_ADDR) | (1 << 0)); + if (of_machine_is_compatible("brcm,bcm7445d0")) + ds->phys_mii_mask |= ((1 << BRCM_PSEUDO_PHY_ADDR) | (1 << 0)); + else + ds->phys_mii_mask = 0; rev = reg_readl(priv, REG_SWITCH_REVISION); priv->hw_params.top_rev = (rev >> SWITCH_TOP_REV_SHIFT) & diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index fd8547c2b79d..561342466076 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1163,7 +1163,7 @@ int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask) newfid = __ffs(ps->fid_mask); ps->fid[port] = newfid; - ps->fid_mask &= (1 << newfid); + ps->fid_mask &= ~(1 << newfid); ps->bridge_mask[fid] &= ~(1 << port); ps->bridge_mask[newfid] = 1 << port; diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c index 41095ebad97f..2d1ce3c5d0dd 100644 --- a/drivers/net/ethernet/3com/3c59x.c +++ b/drivers/net/ethernet/3com/3c59x.c @@ -2382,6 +2382,7 @@ boomerang_interrupt(int irq, void *dev_id) void __iomem *ioaddr; int status; int work_done = max_interrupt_work; + int handled = 0; ioaddr = vp->ioaddr; @@ -2400,6 +2401,7 @@ boomerang_interrupt(int irq, void *dev_id) if ((status & IntLatch) == 0) goto handler_exit; /* No interrupt: shared IRQs can cause this */ + handled = 1; if (status == 0xffff) { /* h/w no longer present (hotplug)? */ if (vortex_debug > 1) @@ -2501,7 +2503,7 @@ boomerang_interrupt(int irq, void *dev_id) handler_exit: vp->handling_irq = 0; spin_unlock(&vp->lock); - return IRQ_HANDLED; + return IRQ_RETVAL(handled); } static int vortex_rx(struct net_device *dev) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c index 661cdaa7ea96..b3bc87fe3764 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c @@ -303,7 +303,8 @@ static void xgbe_set_buffer_data(struct xgbe_buffer_data *bd, get_page(pa->pages); bd->pa = *pa; - bd->dma = pa->pages_dma + pa->pages_offset; + bd->dma_base = pa->pages_dma; + bd->dma_off = pa->pages_offset; bd->dma_len = len; pa->pages_offset += len; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index 506e832c9e9a..a4473d8ff4fa 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -1110,6 +1110,7 @@ static void xgbe_rx_desc_reset(struct xgbe_prv_data *pdata, unsigned int rx_usecs = pdata->rx_usecs; unsigned int rx_frames = pdata->rx_frames; unsigned int inte; + dma_addr_t hdr_dma, buf_dma; if (!rx_usecs && !rx_frames) { /* No coalescing, interrupt for every descriptor */ @@ -1129,10 +1130,12 @@ static void xgbe_rx_desc_reset(struct xgbe_prv_data *pdata, * Set buffer 2 (hi) address to buffer dma address (hi) and * set control bits OWN and INTE */ - rdesc->desc0 = cpu_to_le32(lower_32_bits(rdata->rx.hdr.dma)); - rdesc->desc1 = cpu_to_le32(upper_32_bits(rdata->rx.hdr.dma)); - rdesc->desc2 = cpu_to_le32(lower_32_bits(rdata->rx.buf.dma)); - rdesc->desc3 = cpu_to_le32(upper_32_bits(rdata->rx.buf.dma)); + hdr_dma = rdata->rx.hdr.dma_base + rdata->rx.hdr.dma_off; + buf_dma = rdata->rx.buf.dma_base + rdata->rx.buf.dma_off; + rdesc->desc0 = cpu_to_le32(lower_32_bits(hdr_dma)); + rdesc->desc1 = cpu_to_le32(upper_32_bits(hdr_dma)); + rdesc->desc2 = cpu_to_le32(lower_32_bits(buf_dma)); + rdesc->desc3 = cpu_to_le32(upper_32_bits(buf_dma)); XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, INTE, inte); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 1e9c28d19ef8..aae9d5ecd182 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -1765,8 +1765,9 @@ static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata, /* Start with the header buffer which may contain just the header * or the header plus data */ - dma_sync_single_for_cpu(pdata->dev, rdata->rx.hdr.dma, - rdata->rx.hdr.dma_len, DMA_FROM_DEVICE); + dma_sync_single_range_for_cpu(pdata->dev, rdata->rx.hdr.dma_base, + rdata->rx.hdr.dma_off, + rdata->rx.hdr.dma_len, DMA_FROM_DEVICE); packet = page_address(rdata->rx.hdr.pa.pages) + rdata->rx.hdr.pa.pages_offset; @@ -1778,8 +1779,11 @@ static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata, len -= copy_len; if (len) { /* Add the remaining data as a frag */ - dma_sync_single_for_cpu(pdata->dev, rdata->rx.buf.dma, - rdata->rx.buf.dma_len, DMA_FROM_DEVICE); + dma_sync_single_range_for_cpu(pdata->dev, + rdata->rx.buf.dma_base, + rdata->rx.buf.dma_off, + rdata->rx.buf.dma_len, + DMA_FROM_DEVICE); skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rdata->rx.buf.pa.pages, @@ -1945,8 +1949,9 @@ read_again: if (!skb) error = 1; } else if (rdesc_len) { - dma_sync_single_for_cpu(pdata->dev, - rdata->rx.buf.dma, + dma_sync_single_range_for_cpu(pdata->dev, + rdata->rx.buf.dma_base, + rdata->rx.buf.dma_off, rdata->rx.buf.dma_len, DMA_FROM_DEVICE); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index 63d72a140053..717ce21b6077 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -337,7 +337,8 @@ struct xgbe_buffer_data { struct xgbe_page_alloc pa; struct xgbe_page_alloc pa_unmap; - dma_addr_t dma; + dma_addr_t dma_base; + unsigned long dma_off; unsigned int dma_len; }; diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 909ad7a0d480..4566cdf0bc39 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -1793,7 +1793,7 @@ static int bcm_sysport_probe(struct platform_device *pdev) macaddr = of_get_mac_address(dn); if (!macaddr || !is_valid_ether_addr(macaddr)) { dev_warn(&pdev->dev, "using random Ethernet MAC\n"); - random_ether_addr(dev->dev_addr); + eth_hw_addr_random(dev); } else { ether_addr_copy(dev->dev_addr, macaddr); } diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index b43b2cb9b830..64c1e9db6b0b 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -1230,7 +1230,6 @@ static struct sk_buff *bcmgenet_put_tx_csum(struct net_device *dev, new_skb = skb_realloc_headroom(skb, sizeof(*status)); dev_kfree_skb(skb); if (!new_skb) { - dev->stats.tx_errors++; dev->stats.tx_dropped++; return NULL; } @@ -1465,7 +1464,6 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring, if (unlikely(!skb)) { dev->stats.rx_dropped++; - dev->stats.rx_errors++; goto next; } @@ -1493,7 +1491,6 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring, if (unlikely(!(dma_flag & DMA_EOP) || !(dma_flag & DMA_SOP))) { netif_err(priv, rx_status, dev, "dropping fragmented packet!\n"); - dev->stats.rx_dropped++; dev->stats.rx_errors++; dev_kfree_skb_any(skb); goto next; @@ -1515,7 +1512,6 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring, dev->stats.rx_frame_errors++; if (dma_flag & DMA_RX_LG) dev->stats.rx_length_errors++; - dev->stats.rx_dropped++; dev->stats.rx_errors++; dev_kfree_skb_any(skb); goto next; diff --git a/drivers/net/ethernet/broadcom/sb1250-mac.c b/drivers/net/ethernet/broadcom/sb1250-mac.c index ac27e24264a5..f557a2aaec23 100644 --- a/drivers/net/ethernet/broadcom/sb1250-mac.c +++ b/drivers/net/ethernet/broadcom/sb1250-mac.c @@ -1508,16 +1508,7 @@ static void sbmac_channel_start(struct sbmac_softc *s) __raw_writeq(reg, port); port = s->sbm_base + R_MAC_ETHERNET_ADDR; -#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS - /* - * Pass1 SOCs do not receive packets addressed to the - * destination address in the R_MAC_ETHERNET_ADDR register. - * Set the value to zero. - */ - __raw_writeq(0, port); -#else __raw_writeq(reg, port); -#endif /* * Set the receive filter for no packets, and write values diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index caeb39561567..bf9eb2ecf960 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -104,6 +104,57 @@ static void *macb_rx_buffer(struct macb *bp, unsigned int index) return bp->rx_buffers + bp->rx_buffer_size * macb_rx_ring_wrap(index); } +/* I/O accessors */ +static u32 hw_readl_native(struct macb *bp, int offset) +{ + return __raw_readl(bp->regs + offset); +} + +static void hw_writel_native(struct macb *bp, int offset, u32 value) +{ + __raw_writel(value, bp->regs + offset); +} + +static u32 hw_readl(struct macb *bp, int offset) +{ + return readl_relaxed(bp->regs + offset); +} + +static void hw_writel(struct macb *bp, int offset, u32 value) +{ + writel_relaxed(value, bp->regs + offset); +} + +/* + * Find the CPU endianness by using the loopback bit of NCR register. When the + * CPU is in big endian we need to program swaped mode for management + * descriptor access. + */ +static bool hw_is_native_io(void __iomem *addr) +{ + u32 value = MACB_BIT(LLB); + + __raw_writel(value, addr + MACB_NCR); + value = __raw_readl(addr + MACB_NCR); + + /* Write 0 back to disable everything */ + __raw_writel(0, addr + MACB_NCR); + + return value == MACB_BIT(LLB); +} + +static bool hw_is_gem(void __iomem *addr, bool native_io) +{ + u32 id; + + if (native_io) + id = __raw_readl(addr + MACB_MID); + else + id = readl_relaxed(addr + MACB_MID); + + return MACB_BFEXT(IDNUM, id) >= 0x2; +} + static void macb_set_hwaddr(struct macb *bp) { u32 bottom; @@ -160,7 +211,7 @@ static void macb_get_hwaddr(struct macb *bp) } } - netdev_info(bp->dev, "invalid hw address, using random\n"); + dev_info(&bp->pdev->dev, "invalid hw address, using random\n"); eth_hw_addr_random(bp->dev); } @@ -252,7 +303,6 @@ static void macb_handle_link_change(struct net_device *dev) struct macb *bp = netdev_priv(dev); struct phy_device *phydev = bp->phy_dev; unsigned long flags; - int status_change = 0; spin_lock_irqsave(&bp->lock, flags); @@ -449,14 +499,14 @@ err_out: static void macb_update_stats(struct macb *bp) { - u32 __iomem *reg = bp->regs + MACB_PFR; u32 *p = &bp->hw_stats.macb.rx_pause_frames; u32 *end = &bp->hw_stats.macb.tx_pause_frames + 1; + int offset = MACB_PFR; WARN_ON((unsigned long)(end - p - 1) != (MACB_TPF - MACB_PFR) / 4); - for(; p < end; p++, reg++) - *p += readl_relaxed(reg); + for(; p < end; p++, offset += 4) + *p += bp->macb_reg_readl(bp, offset); } static int macb_halt_tx(struct macb *bp) @@ -1107,12 +1157,6 @@ static void macb_poll_controller(struct net_device *dev) } #endif -static inline unsigned int macb_count_tx_descriptors(struct macb *bp, - unsigned int len) -{ - return (len + bp->max_tx_length - 1) / bp->max_tx_length; -} - static unsigned int macb_tx_map(struct macb *bp, struct macb_queue *queue, struct sk_buff *skb) @@ -1263,11 +1307,11 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) * socket buffer: skb fragments of jumbo frames may need to be * splitted into many buffer descriptors. */ - count = macb_count_tx_descriptors(bp, skb_headlen(skb)); + count = DIV_ROUND_UP(skb_headlen(skb), bp->max_tx_length); nr_frags = skb_shinfo(skb)->nr_frags; for (f = 0; f < nr_frags; f++) { frag_size = skb_frag_size(&skb_shinfo(skb)->frags[f]); - count += macb_count_tx_descriptors(bp, frag_size); + count += DIV_ROUND_UP(frag_size, bp->max_tx_length); } spin_lock_irqsave(&bp->lock, flags); @@ -1603,7 +1647,6 @@ static u32 macb_dbw(struct macb *bp) static void macb_configure_dma(struct macb *bp) { u32 dmacfg; - u32 tmp, ncr; if (macb_is_gem(bp)) { dmacfg = gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L); @@ -1613,22 +1656,11 @@ static void macb_configure_dma(struct macb *bp) dmacfg |= GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L); dmacfg &= ~GEM_BIT(ENDIA_PKT); - /* Find the CPU endianness by using the loopback bit of net_ctrl - * register. save it first. When the CPU is in big endian we - * need to program swaped mode for management descriptor access. - */ - ncr = macb_readl(bp, NCR); - __raw_writel(MACB_BIT(LLB), bp->regs + MACB_NCR); - tmp = __raw_readl(bp->regs + MACB_NCR); - - if (tmp == MACB_BIT(LLB)) + if (bp->native_io) dmacfg &= ~GEM_BIT(ENDIA_DESC); else dmacfg |= GEM_BIT(ENDIA_DESC); /* CPU in big endian */ - /* Restore net_ctrl */ - macb_writel(bp, NCR, ncr); - if (bp->dev->features & NETIF_F_HW_CSUM) dmacfg |= GEM_BIT(TXCOEN); else @@ -1897,19 +1929,19 @@ static int macb_change_mtu(struct net_device *dev, int new_mtu) static void gem_update_stats(struct macb *bp) { - int i; + unsigned int i; u32 *p = &bp->hw_stats.gem.tx_octets_31_0; for (i = 0; i < GEM_STATS_LEN; ++i, ++p) { u32 offset = gem_statistics[i].offset; - u64 val = readl_relaxed(bp->regs + offset); + u64 val = bp->macb_reg_readl(bp, offset); bp->ethtool_stats[i] += val; *p += val; if (offset == GEM_OCTTXL || offset == GEM_OCTRXL) { /* Add GEM_OCTTXH, GEM_OCTRXH */ - val = readl_relaxed(bp->regs + offset + 4); + val = bp->macb_reg_readl(bp, offset + 4); bp->ethtool_stats[i] += ((u64)val) << 32; *(++p) += val; } @@ -1976,7 +2008,7 @@ static int gem_get_sset_count(struct net_device *dev, int sset) static void gem_get_ethtool_strings(struct net_device *dev, u32 sset, u8 *p) { - int i; + unsigned int i; switch (sset) { case ETH_SS_STATS: @@ -2190,7 +2222,7 @@ static void macb_configure_caps(struct macb *bp, const struct macb_config *dt_co if (dt_conf) bp->caps = dt_conf->caps; - if (macb_is_gem_hw(bp->regs)) { + if (hw_is_gem(bp->regs, bp->native_io)) { bp->caps |= MACB_CAPS_MACB_IS_GEM; dcfg = gem_readl(bp, DCFG1); @@ -2201,10 +2233,11 @@ static void macb_configure_caps(struct macb *bp, const struct macb_config *dt_co bp->caps |= MACB_CAPS_FIFO_MODE; } - netdev_dbg(bp->dev, "Cadence caps 0x%08x\n", bp->caps); + dev_dbg(&bp->pdev->dev, "Cadence caps 0x%08x\n", bp->caps); } static void macb_probe_queues(void __iomem *mem, + bool native_io, unsigned int *queue_mask, unsigned int *num_queues) { @@ -2219,7 +2252,7 @@ static void macb_probe_queues(void __iomem *mem, * we are early in the probe process and don't have the * MACB_CAPS_MACB_IS_GEM flag positioned */ - if (!macb_is_gem_hw(mem)) + if (!hw_is_gem(mem, native_io)) return; /* bit 0 is never set but queue 0 always exists */ @@ -2786,6 +2819,7 @@ static int macb_probe(struct platform_device *pdev) struct clk *pclk, *hclk, *tx_clk; unsigned int queue_mask, num_queues; struct macb_platform_data *pdata; + bool native_io; struct phy_device *phydev; struct net_device *dev; struct resource *regs; @@ -2794,6 +2828,11 @@ static int macb_probe(struct platform_device *pdev) struct macb *bp; int err; + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mem = devm_ioremap_resource(&pdev->dev, regs); + if (IS_ERR(mem)) + return PTR_ERR(mem); + if (np) { const struct of_device_id *match; @@ -2809,14 +2848,9 @@ static int macb_probe(struct platform_device *pdev) if (err) return err; - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mem = devm_ioremap_resource(&pdev->dev, regs); - if (IS_ERR(mem)) { - err = PTR_ERR(mem); - goto err_disable_clocks; - } + native_io = hw_is_native_io(mem); - macb_probe_queues(mem, &queue_mask, &num_queues); + macb_probe_queues(mem, native_io, &queue_mask, &num_queues); dev = alloc_etherdev_mq(sizeof(*bp), num_queues); if (!dev) { err = -ENOMEM; @@ -2831,6 +2865,14 @@ static int macb_probe(struct platform_device *pdev) bp->pdev = pdev; bp->dev = dev; bp->regs = mem; + bp->native_io = native_io; + if (native_io) { + bp->macb_reg_readl = hw_readl_native; + bp->macb_reg_writel = hw_writel_native; + } else { + bp->macb_reg_readl = hw_readl; + bp->macb_reg_writel = hw_writel; + } bp->num_queues = num_queues; bp->queue_mask = queue_mask; if (macb_config) @@ -2838,9 +2880,8 @@ static int macb_probe(struct platform_device *pdev) bp->pclk = pclk; bp->hclk = hclk; bp->tx_clk = tx_clk; - if (macb_config->jumbo_max_len) { + if (macb_config) bp->jumbo_max_len = macb_config->jumbo_max_len; - } spin_lock_init(&bp->lock); diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index d74655993d4b..1895b6b2addd 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -429,18 +429,12 @@ | GEM_BF(name, value)) /* Register access macros */ -#define macb_readl(port,reg) \ - readl_relaxed((port)->regs + MACB_##reg) -#define macb_writel(port,reg,value) \ - writel_relaxed((value), (port)->regs + MACB_##reg) -#define gem_readl(port, reg) \ - readl_relaxed((port)->regs + GEM_##reg) -#define gem_writel(port, reg, value) \ - writel_relaxed((value), (port)->regs + GEM_##reg) -#define queue_readl(queue, reg) \ - readl_relaxed((queue)->bp->regs + (queue)->reg) -#define queue_writel(queue, reg, value) \ - writel_relaxed((value), (queue)->bp->regs + (queue)->reg) +#define macb_readl(port, reg) (port)->macb_reg_readl((port), MACB_##reg) +#define macb_writel(port, reg, value) (port)->macb_reg_writel((port), MACB_##reg, (value)) +#define gem_readl(port, reg) (port)->macb_reg_readl((port), GEM_##reg) +#define gem_writel(port, reg, value) (port)->macb_reg_writel((port), GEM_##reg, (value)) +#define queue_readl(queue, reg) (queue)->bp->macb_reg_readl((queue)->bp, (queue)->reg) +#define queue_writel(queue, reg, value) (queue)->bp->macb_reg_writel((queue)->bp, (queue)->reg, (value)) /* Conditional GEM/MACB macros. These perform the operation to the correct * register dependent on whether the device is a GEM or a MACB. For registers @@ -785,6 +779,11 @@ struct macb_queue { struct macb { void __iomem *regs; + bool native_io; + + /* hardware IO accessors */ + u32 (*macb_reg_readl)(struct macb *bp, int offset); + void (*macb_reg_writel)(struct macb *bp, int offset, u32 value); unsigned int rx_tail; unsigned int rx_prepared_head; @@ -817,9 +816,9 @@ struct macb { struct mii_bus *mii_bus; struct phy_device *phy_dev; - unsigned int link; - unsigned int speed; - unsigned int duplex; + int link; + int speed; + int duplex; u32 caps; unsigned int dma_burst_length; @@ -843,9 +842,4 @@ static inline bool macb_is_gem(struct macb *bp) return !!(bp->caps & MACB_CAPS_MACB_IS_GEM); } -static inline bool macb_is_gem_hw(void __iomem *addr) -{ - return !!(MACB_BFEXT(IDNUM, readl_relaxed(addr + MACB_MID)) >= 0x2); -} - #endif /* _MACB_H */ diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h index dda8a02b7322..8aee250904ec 100644 --- a/drivers/net/ethernet/cavium/thunder/nic.h +++ b/drivers/net/ethernet/cavium/thunder/nic.h @@ -125,6 +125,15 @@ */ #define NICPF_CLK_PER_INT_TICK 2 +/* Time to wait before we decide that a SQ is stuck. + * + * Since both pkt rx and tx notifications are done with same CQ, + * when packets are being received at very high rate (eg: L2 forwarding) + * then freeing transmitted skbs will be delayed and watchdog + * will kick in, resetting interface. Hence keeping this value high. + */ +#define NICVF_TX_TIMEOUT (50 * HZ) + struct nicvf_cq_poll { u8 cq_idx; /* Completion queue index */ struct napi_struct napi; @@ -216,8 +225,9 @@ struct nicvf_drv_stats { /* Tx */ u64 tx_frames_ok; u64 tx_drops; - u64 tx_busy; u64 tx_tso; + u64 txq_stop; + u64 txq_wake; }; struct nicvf { diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c index 16bd2d772db9..a4228e664567 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c @@ -66,9 +66,10 @@ static const struct nicvf_stat nicvf_drv_stats[] = { NICVF_DRV_STAT(rx_frames_jumbo), NICVF_DRV_STAT(rx_drops), NICVF_DRV_STAT(tx_frames_ok), - NICVF_DRV_STAT(tx_busy), NICVF_DRV_STAT(tx_tso), NICVF_DRV_STAT(tx_drops), + NICVF_DRV_STAT(txq_stop), + NICVF_DRV_STAT(txq_wake), }; static const struct nicvf_stat nicvf_queue_stats[] = { @@ -126,6 +127,7 @@ static void nicvf_set_msglevel(struct net_device *netdev, u32 lvl) static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data) { + struct nicvf *nic = netdev_priv(netdev); int stats, qidx; if (sset != ETH_SS_STATS) @@ -141,7 +143,7 @@ static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data) data += ETH_GSTRING_LEN; } - for (qidx = 0; qidx < MAX_RCV_QUEUES_PER_QS; qidx++) { + for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) { for (stats = 0; stats < nicvf_n_queue_stats; stats++) { sprintf(data, "rxq%d: %s", qidx, nicvf_queue_stats[stats].name); @@ -149,7 +151,7 @@ static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data) } } - for (qidx = 0; qidx < MAX_SND_QUEUES_PER_QS; qidx++) { + for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) { for (stats = 0; stats < nicvf_n_queue_stats; stats++) { sprintf(data, "txq%d: %s", qidx, nicvf_queue_stats[stats].name); @@ -170,12 +172,14 @@ static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data) static int nicvf_get_sset_count(struct net_device *netdev, int sset) { + struct nicvf *nic = netdev_priv(netdev); + if (sset != ETH_SS_STATS) return -EINVAL; return nicvf_n_hw_stats + nicvf_n_drv_stats + (nicvf_n_queue_stats * - (MAX_RCV_QUEUES_PER_QS + MAX_SND_QUEUES_PER_QS)) + + (nic->qs->rq_cnt + nic->qs->sq_cnt)) + BGX_RX_STATS_COUNT + BGX_TX_STATS_COUNT; } @@ -197,13 +201,13 @@ static void nicvf_get_ethtool_stats(struct net_device *netdev, *(data++) = ((u64 *)&nic->drv_stats) [nicvf_drv_stats[stat].index]; - for (qidx = 0; qidx < MAX_RCV_QUEUES_PER_QS; qidx++) { + for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) { for (stat = 0; stat < nicvf_n_queue_stats; stat++) *(data++) = ((u64 *)&nic->qs->rq[qidx].stats) [nicvf_queue_stats[stat].index]; } - for (qidx = 0; qidx < MAX_SND_QUEUES_PER_QS; qidx++) { + for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) { for (stat = 0; stat < nicvf_n_queue_stats; stat++) *(data++) = ((u64 *)&nic->qs->sq[qidx].stats) [nicvf_queue_stats[stat].index]; @@ -543,6 +547,7 @@ static int nicvf_set_channels(struct net_device *dev, { struct nicvf *nic = netdev_priv(dev); int err = 0; + bool if_up = netif_running(dev); if (!channel->rx_count || !channel->tx_count) return -EINVAL; @@ -551,6 +556,9 @@ static int nicvf_set_channels(struct net_device *dev, if (channel->tx_count > MAX_SND_QUEUES_PER_QS) return -EINVAL; + if (if_up) + nicvf_stop(dev); + nic->qs->rq_cnt = channel->rx_count; nic->qs->sq_cnt = channel->tx_count; nic->qs->cq_cnt = max(nic->qs->rq_cnt, nic->qs->sq_cnt); @@ -559,11 +567,9 @@ static int nicvf_set_channels(struct net_device *dev, if (err) return err; - if (!netif_running(dev)) - return err; + if (if_up) + nicvf_open(dev); - nicvf_stop(dev); - nicvf_open(dev); netdev_info(dev, "Setting num Tx rings to %d, Rx rings to %d success\n", nic->qs->sq_cnt, nic->qs->rq_cnt); diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index 8b119a035b7e..3b90afb8c293 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -234,7 +234,7 @@ static void nicvf_handle_mbx_intr(struct nicvf *nic) nic->duplex == DUPLEX_FULL ? "Full duplex" : "Half duplex"); netif_carrier_on(nic->netdev); - netif_tx_wake_all_queues(nic->netdev); + netif_tx_start_all_queues(nic->netdev); } else { netdev_info(nic->netdev, "%s: Link is Down\n", nic->netdev->name); @@ -425,6 +425,7 @@ static void nicvf_snd_pkt_handler(struct net_device *netdev, if (skb) { prefetch(skb); dev_consume_skb_any(skb); + sq->skbuff[cqe_tx->sqe_ptr] = (u64)NULL; } } @@ -476,12 +477,13 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev, static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx, struct napi_struct *napi, int budget) { - int processed_cqe, work_done = 0; + int processed_cqe, work_done = 0, tx_done = 0; int cqe_count, cqe_head; struct nicvf *nic = netdev_priv(netdev); struct queue_set *qs = nic->qs; struct cmp_queue *cq = &qs->cq[cq_idx]; struct cqe_rx_t *cq_desc; + struct netdev_queue *txq; spin_lock_bh(&cq->lock); loop: @@ -496,8 +498,8 @@ loop: cqe_head = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_HEAD, cq_idx) >> 9; cqe_head &= 0xFFFF; - netdev_dbg(nic->netdev, "%s cqe_count %d cqe_head %d\n", - __func__, cqe_count, cqe_head); + netdev_dbg(nic->netdev, "%s CQ%d cqe_count %d cqe_head %d\n", + __func__, cq_idx, cqe_count, cqe_head); while (processed_cqe < cqe_count) { /* Get the CQ descriptor */ cq_desc = (struct cqe_rx_t *)GET_CQ_DESC(cq, cqe_head); @@ -511,8 +513,8 @@ loop: break; } - netdev_dbg(nic->netdev, "cq_desc->cqe_type %d\n", - cq_desc->cqe_type); + netdev_dbg(nic->netdev, "CQ%d cq_desc->cqe_type %d\n", + cq_idx, cq_desc->cqe_type); switch (cq_desc->cqe_type) { case CQE_TYPE_RX: nicvf_rcv_pkt_handler(netdev, napi, cq, @@ -522,6 +524,7 @@ loop: case CQE_TYPE_SEND: nicvf_snd_pkt_handler(netdev, cq, (void *)cq_desc, CQE_TYPE_SEND); + tx_done++; break; case CQE_TYPE_INVALID: case CQE_TYPE_RX_SPLIT: @@ -532,8 +535,9 @@ loop: } processed_cqe++; } - netdev_dbg(nic->netdev, "%s processed_cqe %d work_done %d budget %d\n", - __func__, processed_cqe, work_done, budget); + netdev_dbg(nic->netdev, + "%s CQ%d processed_cqe %d work_done %d budget %d\n", + __func__, cq_idx, processed_cqe, work_done, budget); /* Ring doorbell to inform H/W to reuse processed CQEs */ nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_DOOR, @@ -543,6 +547,19 @@ loop: goto loop; done: + /* Wakeup TXQ if its stopped earlier due to SQ full */ + if (tx_done) { + txq = netdev_get_tx_queue(netdev, cq_idx); + if (netif_tx_queue_stopped(txq)) { + netif_tx_start_queue(txq); + nic->drv_stats.txq_wake++; + if (netif_msg_tx_err(nic)) + netdev_warn(netdev, + "%s: Transmit queue wakeup SQ%d\n", + netdev->name, cq_idx); + } + } + spin_unlock_bh(&cq->lock); return work_done; } @@ -554,15 +571,10 @@ static int nicvf_poll(struct napi_struct *napi, int budget) struct net_device *netdev = napi->dev; struct nicvf *nic = netdev_priv(netdev); struct nicvf_cq_poll *cq; - struct netdev_queue *txq; cq = container_of(napi, struct nicvf_cq_poll, napi); work_done = nicvf_cq_intr_handler(netdev, cq->cq_idx, napi, budget); - txq = netdev_get_tx_queue(netdev, cq->cq_idx); - if (netif_tx_queue_stopped(txq)) - netif_tx_wake_queue(txq); - if (work_done < budget) { /* Slow packet rate, exit polling */ napi_complete(napi); @@ -833,9 +845,9 @@ static netdev_tx_t nicvf_xmit(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_OK; } - if (!nicvf_sq_append_skb(nic, skb) && !netif_tx_queue_stopped(txq)) { + if (!netif_tx_queue_stopped(txq) && !nicvf_sq_append_skb(nic, skb)) { netif_tx_stop_queue(txq); - nic->drv_stats.tx_busy++; + nic->drv_stats.txq_stop++; if (netif_msg_tx_err(nic)) netdev_warn(netdev, "%s: Transmit ring full, stopping SQ%d\n", @@ -859,7 +871,6 @@ int nicvf_stop(struct net_device *netdev) nicvf_send_msg_to_pf(nic, &mbx); netif_carrier_off(netdev); - netif_tx_disable(netdev); /* Disable RBDR & QS error interrupts */ for (qidx = 0; qidx < qs->rbdr_cnt; qidx++) { @@ -894,6 +905,8 @@ int nicvf_stop(struct net_device *netdev) kfree(cq_poll); } + netif_tx_disable(netdev); + /* Free resources */ nicvf_config_data_transfer(nic, false); @@ -988,6 +1001,9 @@ int nicvf_open(struct net_device *netdev) for (qidx = 0; qidx < qs->rbdr_cnt; qidx++) nicvf_enable_intr(nic, NICVF_INTR_RBDR, qidx); + nic->drv_stats.txq_stop = 0; + nic->drv_stats.txq_wake = 0; + netif_carrier_on(netdev); netif_tx_start_all_queues(netdev); @@ -1278,6 +1294,7 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->hw_features = netdev->features; netdev->netdev_ops = &nicvf_netdev_ops; + netdev->watchdog_timeo = NICVF_TX_TIMEOUT; INIT_WORK(&nic->reset_task, nicvf_reset_task); @@ -1318,11 +1335,17 @@ static void nicvf_remove(struct pci_dev *pdev) pci_disable_device(pdev); } +static void nicvf_shutdown(struct pci_dev *pdev) +{ + nicvf_remove(pdev); +} + static struct pci_driver nicvf_driver = { .name = DRV_NAME, .id_table = nicvf_id_table, .probe = nicvf_probe, .remove = nicvf_remove, + .shutdown = nicvf_shutdown, }; static int __init nicvf_init_module(void) diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c index d69d228d11a0..ca4240aa6d15 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c @@ -103,9 +103,11 @@ static inline int nicvf_alloc_rcv_buffer(struct nicvf *nic, gfp_t gfp, /* Allocate a new page */ if (!nic->rb_page) { - nic->rb_page = alloc_pages(gfp | __GFP_COMP, order); + nic->rb_page = alloc_pages(gfp | __GFP_COMP | __GFP_NOWARN, + order); if (!nic->rb_page) { - netdev_err(nic->netdev, "Failed to allocate new rcv buffer\n"); + netdev_err(nic->netdev, + "Failed to allocate new rcv buffer\n"); return -ENOMEM; } nic->rb_page_offset = 0; @@ -382,7 +384,8 @@ static void nicvf_free_snd_queue(struct nicvf *nic, struct snd_queue *sq) return; if (sq->tso_hdrs) - dma_free_coherent(&nic->pdev->dev, sq->dmem.q_len, + dma_free_coherent(&nic->pdev->dev, + sq->dmem.q_len * TSO_HEADER_SIZE, sq->tso_hdrs, sq->tso_hdrs_phys); kfree(sq->skbuff); @@ -863,10 +866,11 @@ void nicvf_sq_free_used_descs(struct net_device *netdev, struct snd_queue *sq, continue; } skb = (struct sk_buff *)sq->skbuff[sq->head]; + if (skb) + dev_kfree_skb_any(skb); atomic64_add(1, (atomic64_t *)&netdev->stats.tx_packets); atomic64_add(hdr->tot_len, (atomic64_t *)&netdev->stats.tx_bytes); - dev_kfree_skb_any(skb); nicvf_put_sq_desc(sq, hdr->subdesc_cnt + 1); } } @@ -992,7 +996,7 @@ static inline void nicvf_sq_add_gather_subdesc(struct snd_queue *sq, int qentry, memset(gather, 0, SND_QUEUE_DESC_SIZE); gather->subdesc_type = SQ_DESC_TYPE_GATHER; - gather->ld_type = NIC_SEND_LD_TYPE_E_LDWB; + gather->ld_type = NIC_SEND_LD_TYPE_E_LDD; gather->size = size; gather->addr = data; } @@ -1048,7 +1052,7 @@ static int nicvf_sq_append_tso(struct nicvf *nic, struct snd_queue *sq, } nicvf_sq_add_hdr_subdesc(sq, hdr_qentry, seg_subdescs - 1, skb, seg_len); - sq->skbuff[hdr_qentry] = 0; + sq->skbuff[hdr_qentry] = (u64)NULL; qentry = nicvf_get_nxt_sqentry(sq, qentry); desc_cnt += seg_subdescs; @@ -1062,6 +1066,7 @@ static int nicvf_sq_append_tso(struct nicvf *nic, struct snd_queue *sq, /* Inform HW to xmit all TSO segments */ nicvf_queue_reg_write(nic, NIC_QSET_SQ_0_7_DOOR, skb_get_queue_mapping(skb), desc_cnt); + nic->drv_stats.tx_tso++; return 1; } diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h index 8341bdf755d1..f0937b7bfe9f 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h @@ -62,7 +62,7 @@ #define SND_QUEUE_CNT 8 #define CMP_QUEUE_CNT 8 /* Max of RCV and SND qcount */ -#define SND_QSIZE SND_QUEUE_SIZE4 +#define SND_QSIZE SND_QUEUE_SIZE2 #define SND_QUEUE_LEN (1ULL << (SND_QSIZE + 10)) #define MAX_SND_QUEUE_LEN (1ULL << (SND_QUEUE_SIZE6 + 10)) #define SND_QUEUE_THRESH 2ULL @@ -70,7 +70,10 @@ /* Since timestamp not enabled, otherwise 2 */ #define MAX_CQE_PER_PKT_XMIT 1 -#define CMP_QSIZE CMP_QUEUE_SIZE4 +/* Keep CQ and SQ sizes same, if timestamping + * is enabled this equation will change. + */ +#define CMP_QSIZE CMP_QUEUE_SIZE2 #define CMP_QUEUE_LEN (1ULL << (CMP_QSIZE + 10)) #define CMP_QUEUE_CQE_THRESH 0 #define CMP_QUEUE_TIMER_THRESH 220 /* 10usec */ @@ -87,7 +90,12 @@ #define MAX_CQES_FOR_TX ((SND_QUEUE_LEN / MIN_SQ_DESC_PER_PKT_XMIT) * \ MAX_CQE_PER_PKT_XMIT) -#define RQ_CQ_DROP ((CMP_QUEUE_LEN - MAX_CQES_FOR_TX) / 256) +/* Calculate number of CQEs to reserve for all SQEs. + * Its 1/256th level of CQ size. + * '+ 1' to account for pipelining + */ +#define RQ_CQ_DROP ((256 / (CMP_QUEUE_LEN / \ + (CMP_QUEUE_LEN - MAX_CQES_FOR_TX))) + 1) /* Descriptor size in bytes */ #define SND_QUEUE_DESC_SIZE 16 diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c index 633ec05dfe05..b961a89dc626 100644 --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c @@ -673,7 +673,10 @@ static void bgx_lmac_disable(struct bgx *bgx, u8 lmacid) bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cmrx_cfg); bgx_flush_dmac_addrs(bgx, lmacid); - if (lmac->phydev) + if ((bgx->lmac_type != BGX_MODE_XFI) && + (bgx->lmac_type != BGX_MODE_XLAUI) && + (bgx->lmac_type != BGX_MODE_40G_KR) && + (bgx->lmac_type != BGX_MODE_10G_KR) && lmac->phydev) phy_disconnect(lmac->phydev); lmac->phydev = NULL; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c index 484eb8c37489..a11485fbb33f 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c @@ -952,16 +952,23 @@ static int devlog_show(struct seq_file *seq, void *v) * eventually have to put a format interpreter in here ... */ seq_printf(seq, "%10d %15llu %8s %8s ", - e->seqno, e->timestamp, + be32_to_cpu(e->seqno), + be64_to_cpu(e->timestamp), (e->level < ARRAY_SIZE(devlog_level_strings) ? devlog_level_strings[e->level] : "UNKNOWN"), (e->facility < ARRAY_SIZE(devlog_facility_strings) ? devlog_facility_strings[e->facility] : "UNKNOWN")); - seq_printf(seq, e->fmt, e->params[0], e->params[1], - e->params[2], e->params[3], e->params[4], - e->params[5], e->params[6], e->params[7]); + seq_printf(seq, e->fmt, + be32_to_cpu(e->params[0]), + be32_to_cpu(e->params[1]), + be32_to_cpu(e->params[2]), + be32_to_cpu(e->params[3]), + be32_to_cpu(e->params[4]), + be32_to_cpu(e->params[5]), + be32_to_cpu(e->params[6]), + be32_to_cpu(e->params[7])); } return 0; } @@ -1043,23 +1050,17 @@ static int devlog_open(struct inode *inode, struct file *file) return ret; } - /* Translate log multi-byte integral elements into host native format - * and determine where the first entry in the log is. + /* Find the earliest (lowest Sequence Number) log entry in the + * circular Device Log. */ for (fseqno = ~((u32)0), index = 0; index < dinfo->nentries; index++) { struct fw_devlog_e *e = &dinfo->log[index]; - int i; __u32 seqno; if (e->timestamp == 0) continue; - e->timestamp = (__force __be64)be64_to_cpu(e->timestamp); seqno = be32_to_cpu(e->seqno); - for (i = 0; i < 8; i++) - e->params[i] = - (__force __be32)be32_to_cpu(e->params[i]); - if (seqno < fseqno) { fseqno = seqno; dinfo->first = index; diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index da2004e2a741..918a8e42139b 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -1170,7 +1170,7 @@ static int enic_poll(struct napi_struct *napi, int budget) wq_work_done, 0 /* dont unmask intr */, 0 /* dont reset intr timer */); - return rq_work_done; + return budget; } if (budget > 0) @@ -1191,6 +1191,7 @@ static int enic_poll(struct napi_struct *napi, int budget) 0 /* don't reset intr timer */); err = vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf); + enic_poll_unlock_napi(&enic->rq[cq_rq], napi); /* Buffer allocation failed. Stay in polling * mode so we can try to fill the ring again. @@ -1208,7 +1209,6 @@ static int enic_poll(struct napi_struct *napi, int budget) napi_complete(napi); vnic_intr_unmask(&enic->intr[intr]); } - enic_poll_unlock_napi(&enic->rq[cq_rq], napi); return rq_work_done; } diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 1eee73cccdf5..99d33e2d35e6 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -562,6 +562,7 @@ struct fec_enet_private { }; void fec_ptp_init(struct platform_device *pdev); +void fec_ptp_stop(struct platform_device *pdev); void fec_ptp_start_cyclecounter(struct net_device *ndev); int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr); int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr); diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 1f89c59b4353..32e3807c650e 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -24,6 +24,7 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/string.h> +#include <linux/pm_runtime.h> #include <linux/ptrace.h> #include <linux/errno.h> #include <linux/ioport.h> @@ -77,6 +78,7 @@ static void fec_enet_itr_coal_init(struct net_device *ndev); #define FEC_ENET_RAEM_V 0x8 #define FEC_ENET_RAFL_V 0x8 #define FEC_ENET_OPD_V 0xFFF0 +#define FEC_MDIO_PM_TIMEOUT 100 /* ms */ static struct platform_device_id fec_devtype[] = { { @@ -1767,7 +1769,13 @@ static void fec_enet_adjust_link(struct net_device *ndev) static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) { struct fec_enet_private *fep = bus->priv; + struct device *dev = &fep->pdev->dev; unsigned long time_left; + int ret = 0; + + ret = pm_runtime_get_sync(dev); + if (IS_ERR_VALUE(ret)) + return ret; fep->mii_timeout = 0; init_completion(&fep->mdio_done); @@ -1783,18 +1791,30 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) if (time_left == 0) { fep->mii_timeout = 1; netdev_err(fep->netdev, "MDIO read timeout\n"); - return -ETIMEDOUT; + ret = -ETIMEDOUT; + goto out; } - /* return value */ - return FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA)); + ret = FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA)); + +out: + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return ret; } static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) { struct fec_enet_private *fep = bus->priv; + struct device *dev = &fep->pdev->dev; unsigned long time_left; + int ret = 0; + + ret = pm_runtime_get_sync(dev); + if (IS_ERR_VALUE(ret)) + return ret; fep->mii_timeout = 0; init_completion(&fep->mdio_done); @@ -1811,10 +1831,13 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, if (time_left == 0) { fep->mii_timeout = 1; netdev_err(fep->netdev, "MDIO write timeout\n"); - return -ETIMEDOUT; + ret = -ETIMEDOUT; } - return 0; + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return ret; } static int fec_enet_clk_enable(struct net_device *ndev, bool enable) @@ -1826,9 +1849,6 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable) ret = clk_prepare_enable(fep->clk_ahb); if (ret) return ret; - ret = clk_prepare_enable(fep->clk_ipg); - if (ret) - goto failed_clk_ipg; if (fep->clk_enet_out) { ret = clk_prepare_enable(fep->clk_enet_out); if (ret) @@ -1852,7 +1872,6 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable) } } else { clk_disable_unprepare(fep->clk_ahb); - clk_disable_unprepare(fep->clk_ipg); if (fep->clk_enet_out) clk_disable_unprepare(fep->clk_enet_out); if (fep->clk_ptp) { @@ -1874,8 +1893,6 @@ failed_clk_ptp: if (fep->clk_enet_out) clk_disable_unprepare(fep->clk_enet_out); failed_clk_enet_out: - clk_disable_unprepare(fep->clk_ipg); -failed_clk_ipg: clk_disable_unprepare(fep->clk_ahb); return ret; @@ -2847,10 +2864,14 @@ fec_enet_open(struct net_device *ndev) struct fec_enet_private *fep = netdev_priv(ndev); int ret; + ret = pm_runtime_get_sync(&fep->pdev->dev); + if (IS_ERR_VALUE(ret)) + return ret; + pinctrl_pm_select_default_state(&fep->pdev->dev); ret = fec_enet_clk_enable(ndev, true); if (ret) - return ret; + goto clk_enable; /* I should reset the ring buffers here, but I don't yet know * a simple way to do that. @@ -2881,6 +2902,9 @@ err_enet_mii_probe: fec_enet_free_buffers(ndev); err_enet_alloc: fec_enet_clk_enable(ndev, false); +clk_enable: + pm_runtime_mark_last_busy(&fep->pdev->dev); + pm_runtime_put_autosuspend(&fep->pdev->dev); pinctrl_pm_select_sleep_state(&fep->pdev->dev); return ret; } @@ -2903,6 +2927,9 @@ fec_enet_close(struct net_device *ndev) fec_enet_clk_enable(ndev, false); pinctrl_pm_select_sleep_state(&fep->pdev->dev); + pm_runtime_mark_last_busy(&fep->pdev->dev); + pm_runtime_put_autosuspend(&fep->pdev->dev); + fec_enet_free_buffers(ndev); return 0; @@ -3115,8 +3142,8 @@ static int fec_enet_init(struct net_device *ndev) fep->bufdesc_size; /* Allocate memory for buffer descriptors. */ - cbd_base = dma_alloc_coherent(NULL, bd_size, &bd_dma, - GFP_KERNEL); + cbd_base = dmam_alloc_coherent(&fep->pdev->dev, bd_size, &bd_dma, + GFP_KERNEL); if (!cbd_base) { return -ENOMEM; } @@ -3388,6 +3415,10 @@ fec_probe(struct platform_device *pdev) if (ret) goto failed_clk; + ret = clk_prepare_enable(fep->clk_ipg); + if (ret) + goto failed_clk_ipg; + fep->reg_phy = devm_regulator_get(&pdev->dev, "phy"); if (!IS_ERR(fep->reg_phy)) { ret = regulator_enable(fep->reg_phy); @@ -3400,6 +3431,11 @@ fec_probe(struct platform_device *pdev) fep->reg_phy = NULL; } + pm_runtime_set_autosuspend_delay(&pdev->dev, FEC_MDIO_PM_TIMEOUT); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + fec_reset_phy(pdev); if (fep->bufdesc_ex) @@ -3447,6 +3483,10 @@ fec_probe(struct platform_device *pdev) fep->rx_copybreak = COPYBREAK_DEFAULT; INIT_WORK(&fep->tx_timeout_work, fec_enet_timeout_work); + + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); + return 0; failed_register: @@ -3454,9 +3494,12 @@ failed_register: failed_mii_init: failed_irq: failed_init: + fec_ptp_stop(pdev); if (fep->reg_phy) regulator_disable(fep->reg_phy); failed_regulator: + clk_disable_unprepare(fep->clk_ipg); +failed_clk_ipg: fec_enet_clk_enable(ndev, false); failed_clk: failed_phy: @@ -3473,14 +3516,12 @@ fec_drv_remove(struct platform_device *pdev) struct net_device *ndev = platform_get_drvdata(pdev); struct fec_enet_private *fep = netdev_priv(ndev); - cancel_delayed_work_sync(&fep->time_keep); cancel_work_sync(&fep->tx_timeout_work); + fec_ptp_stop(pdev); unregister_netdev(ndev); fec_enet_mii_remove(fep); if (fep->reg_phy) regulator_disable(fep->reg_phy); - if (fep->ptp_clock) - ptp_clock_unregister(fep->ptp_clock); of_node_put(fep->phy_node); free_netdev(ndev); @@ -3568,7 +3609,28 @@ failed_clk: return ret; } -static SIMPLE_DEV_PM_OPS(fec_pm_ops, fec_suspend, fec_resume); +static int __maybe_unused fec_runtime_suspend(struct device *dev) +{ + struct net_device *ndev = dev_get_drvdata(dev); + struct fec_enet_private *fep = netdev_priv(ndev); + + clk_disable_unprepare(fep->clk_ipg); + + return 0; +} + +static int __maybe_unused fec_runtime_resume(struct device *dev) +{ + struct net_device *ndev = dev_get_drvdata(dev); + struct fec_enet_private *fep = netdev_priv(ndev); + + return clk_prepare_enable(fep->clk_ipg); +} + +static const struct dev_pm_ops fec_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(fec_suspend, fec_resume) + SET_RUNTIME_PM_OPS(fec_runtime_suspend, fec_runtime_resume, NULL) +}; static struct platform_driver fec_driver = { .driver = { diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index a15663ad7f5e..f457a23d0bfb 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -604,6 +604,16 @@ void fec_ptp_init(struct platform_device *pdev) schedule_delayed_work(&fep->time_keep, HZ); } +void fec_ptp_stop(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct fec_enet_private *fep = netdev_priv(ndev); + + cancel_delayed_work_sync(&fep->time_keep); + if (fep->ptp_clock) + ptp_clock_unregister(fep->ptp_clock); +} + /** * fec_ptp_check_pps_event * @fep: the fec_enet_private structure handle diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index ff875028fdff..2b7610f341b0 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -565,22 +565,6 @@ static void gfar_ints_enable(struct gfar_private *priv) } } -static void lock_tx_qs(struct gfar_private *priv) -{ - int i; - - for (i = 0; i < priv->num_tx_queues; i++) - spin_lock(&priv->tx_queue[i]->txlock); -} - -static void unlock_tx_qs(struct gfar_private *priv) -{ - int i; - - for (i = 0; i < priv->num_tx_queues; i++) - spin_unlock(&priv->tx_queue[i]->txlock); -} - static int gfar_alloc_tx_queues(struct gfar_private *priv) { int i; @@ -1376,7 +1360,6 @@ static int gfar_probe(struct platform_device *ofdev) priv->dev = &ofdev->dev; SET_NETDEV_DEV(dev, &ofdev->dev); - spin_lock_init(&priv->bflock); INIT_WORK(&priv->reset_task, gfar_reset_task); platform_set_drvdata(ofdev, priv); @@ -1470,9 +1453,8 @@ static int gfar_probe(struct platform_device *ofdev) goto register_fail; } - device_init_wakeup(&dev->dev, - priv->device_flags & - FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); + device_set_wakeup_capable(&dev->dev, priv->device_flags & + FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); /* fill out IRQ number and name fields */ for (i = 0; i < priv->num_grps; i++) { @@ -1540,48 +1522,37 @@ static int gfar_suspend(struct device *dev) struct gfar_private *priv = dev_get_drvdata(dev); struct net_device *ndev = priv->ndev; struct gfar __iomem *regs = priv->gfargrp[0].regs; - unsigned long flags; u32 tempval; - int magic_packet = priv->wol_en && (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); + if (!netif_running(ndev)) + return 0; + + disable_napi(priv); + netif_tx_lock(ndev); netif_device_detach(ndev); + netif_tx_unlock(ndev); - if (netif_running(ndev)) { + gfar_halt(priv); - local_irq_save(flags); - lock_tx_qs(priv); + if (magic_packet) { + /* Enable interrupt on Magic Packet */ + gfar_write(®s->imask, IMASK_MAG); - gfar_halt_nodisable(priv); + /* Enable Magic Packet mode */ + tempval = gfar_read(®s->maccfg2); + tempval |= MACCFG2_MPEN; + gfar_write(®s->maccfg2, tempval); - /* Disable Tx, and Rx if wake-on-LAN is disabled. */ + /* re-enable the Rx block */ tempval = gfar_read(®s->maccfg1); - - tempval &= ~MACCFG1_TX_EN; - - if (!magic_packet) - tempval &= ~MACCFG1_RX_EN; - + tempval |= MACCFG1_RX_EN; gfar_write(®s->maccfg1, tempval); - unlock_tx_qs(priv); - local_irq_restore(flags); - - disable_napi(priv); - - if (magic_packet) { - /* Enable interrupt on Magic Packet */ - gfar_write(®s->imask, IMASK_MAG); - - /* Enable Magic Packet mode */ - tempval = gfar_read(®s->maccfg2); - tempval |= MACCFG2_MPEN; - gfar_write(®s->maccfg2, tempval); - } else { - phy_stop(priv->phydev); - } + } else { + phy_stop(priv->phydev); } return 0; @@ -1592,37 +1563,26 @@ static int gfar_resume(struct device *dev) struct gfar_private *priv = dev_get_drvdata(dev); struct net_device *ndev = priv->ndev; struct gfar __iomem *regs = priv->gfargrp[0].regs; - unsigned long flags; u32 tempval; int magic_packet = priv->wol_en && (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); - if (!netif_running(ndev)) { - netif_device_attach(ndev); + if (!netif_running(ndev)) return 0; - } - if (!magic_packet && priv->phydev) + if (magic_packet) { + /* Disable Magic Packet mode */ + tempval = gfar_read(®s->maccfg2); + tempval &= ~MACCFG2_MPEN; + gfar_write(®s->maccfg2, tempval); + } else { phy_start(priv->phydev); - - /* Disable Magic Packet mode, in case something - * else woke us up. - */ - local_irq_save(flags); - lock_tx_qs(priv); - - tempval = gfar_read(®s->maccfg2); - tempval &= ~MACCFG2_MPEN; - gfar_write(®s->maccfg2, tempval); + } gfar_start(priv); - unlock_tx_qs(priv); - local_irq_restore(flags); - netif_device_attach(ndev); - enable_napi(priv); return 0; @@ -2045,7 +2005,8 @@ static int register_grp_irqs(struct gfar_priv_grp *grp) /* Install our interrupt handlers for Error, * Transmit, and Receive */ - err = request_irq(gfar_irq(grp, ER)->irq, gfar_error, 0, + err = request_irq(gfar_irq(grp, ER)->irq, gfar_error, + IRQF_NO_SUSPEND, gfar_irq(grp, ER)->name, grp); if (err < 0) { netif_err(priv, intr, dev, "Can't get IRQ %d\n", @@ -2068,7 +2029,8 @@ static int register_grp_irqs(struct gfar_priv_grp *grp) goto rx_irq_fail; } } else { - err = request_irq(gfar_irq(grp, TX)->irq, gfar_interrupt, 0, + err = request_irq(gfar_irq(grp, TX)->irq, gfar_interrupt, + IRQF_NO_SUSPEND, gfar_irq(grp, TX)->name, grp); if (err < 0) { netif_err(priv, intr, dev, "Can't get IRQ %d\n", @@ -2169,8 +2131,6 @@ static int gfar_enet_open(struct net_device *dev) if (err) return err; - device_set_wakeup_enable(&dev->dev, priv->wol_en); - return err; } diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h index daa1d37de642..5545e4103368 100644 --- a/drivers/net/ethernet/freescale/gianfar.h +++ b/drivers/net/ethernet/freescale/gianfar.h @@ -1145,9 +1145,6 @@ struct gfar_private { int oldduplex; int oldlink; - /* Bitfield update lock */ - spinlock_t bflock; - uint32_t msg_enable; struct work_struct reset_task; diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c index fda12fb32ec7..3c0a8f825b63 100644 --- a/drivers/net/ethernet/freescale/gianfar_ethtool.c +++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c @@ -653,7 +653,6 @@ static void gfar_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct gfar_private *priv = netdev_priv(dev); - unsigned long flags; if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) && wol->wolopts != 0) @@ -664,9 +663,7 @@ static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) device_set_wakeup_enable(&dev->dev, wol->wolopts & WAKE_MAGIC); - spin_lock_irqsave(&priv->bflock, flags); - priv->wol_en = !!device_may_wakeup(&dev->dev); - spin_unlock_irqrestore(&priv->bflock, flags); + priv->wol_en = !!device_may_wakeup(&dev->dev); return 0; } diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 370e20ed224c..62e48bc0cb23 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -1462,7 +1462,7 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo, struct mvneta_rx_queue *rxq) { struct net_device *dev = pp->dev; - int rx_done, rx_filled; + int rx_done; u32 rcvd_pkts = 0; u32 rcvd_bytes = 0; @@ -1473,7 +1473,6 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo, rx_todo = rx_done; rx_done = 0; - rx_filled = 0; /* Fairness NAPI loop */ while (rx_done < rx_todo) { @@ -1484,7 +1483,6 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo, int rx_bytes, err; rx_done++; - rx_filled++; rx_status = rx_desc->status; rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE); data = (unsigned char *)rx_desc->buf_cookie; @@ -1524,6 +1522,14 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo, continue; } + /* Refill processing */ + err = mvneta_rx_refill(pp, rx_desc); + if (err) { + netdev_err(dev, "Linux processing - Can't refill\n"); + rxq->missed++; + goto err_drop_frame; + } + skb = build_skb(data, pp->frag_size > PAGE_SIZE ? 0 : pp->frag_size); if (!skb) goto err_drop_frame; @@ -1543,14 +1549,6 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo, mvneta_rx_csum(pp, rx_status, skb); napi_gro_receive(&pp->napi, skb); - - /* Refill processing */ - err = mvneta_rx_refill(pp, rx_desc); - if (err) { - netdev_err(dev, "Linux processing - Can't refill\n"); - rxq->missed++; - rx_filled--; - } } if (rcvd_pkts) { @@ -1563,7 +1561,7 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo, } /* Update rxq management counters */ - mvneta_rxq_desc_num_update(pp, rxq, rx_done, rx_filled); + mvneta_rxq_desc_num_update(pp, rxq, rx_done, rx_done); return rx_done; } diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index 82040137d7d9..0a3202047569 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -686,6 +686,7 @@ static int mlx4_cmd_wait(struct mlx4_dev *dev, u64 in_param, u64 *out_param, { struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd; struct mlx4_cmd_context *context; + long ret_wait; int err = 0; down(&cmd->event_sem); @@ -711,8 +712,20 @@ static int mlx4_cmd_wait(struct mlx4_dev *dev, u64 in_param, u64 *out_param, if (err) goto out_reset; - if (!wait_for_completion_timeout(&context->done, - msecs_to_jiffies(timeout))) { + if (op == MLX4_CMD_SENSE_PORT) { + ret_wait = + wait_for_completion_interruptible_timeout(&context->done, + msecs_to_jiffies(timeout)); + if (ret_wait < 0) { + context->fw_status = 0; + context->out_param = 0; + context->result = 0; + } + } else { + ret_wait = (long)wait_for_completion_timeout(&context->done, + msecs_to_jiffies(timeout)); + } + if (!ret_wait) { mlx4_warn(dev, "command 0x%x timed out (go bit not cleared)\n", op); if (op == MLX4_CMD_NOP) { diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 7a4f20bb7fcb..9c145dddd717 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -246,7 +246,6 @@ static int mlx4_en_prepare_rx_desc(struct mlx4_en_priv *priv, static inline bool mlx4_en_is_ring_empty(struct mlx4_en_rx_ring *ring) { - BUG_ON((u32)(ring->prod - ring->cons) > ring->actual_size); return ring->prod == ring->cons; } diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index aae13adfb492..8e81e53c370e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -601,7 +601,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) continue; mlx4_dbg(dev, "%s: Sending MLX4_PORT_CHANGE_SUBTYPE_DOWN to slave: %d, port:%d\n", __func__, i, port); - s_info = &priv->mfunc.master.vf_oper[slave].vport[port].state; + s_info = &priv->mfunc.master.vf_oper[i].vport[port].state; if (IFLA_VF_LINK_STATE_AUTO == s_info->link_state) { eqe->event.port_change.port = cpu_to_be32( @@ -640,7 +640,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) continue; if (i == mlx4_master_func_num(dev)) continue; - s_info = &priv->mfunc.master.vf_oper[slave].vport[port].state; + s_info = &priv->mfunc.master.vf_oper[i].vport[port].state; if (IFLA_VF_LINK_STATE_AUTO == s_info->link_state) { eqe->event.port_change.port = cpu_to_be32( diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 12fbfcb44d8a..29c2a017a450 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -2273,6 +2273,11 @@ static int mlx4_allocate_default_counters(struct mlx4_dev *dev) } else if (err == -ENOENT) { err = 0; continue; + } else if (mlx4_is_slave(dev) && err == -EINVAL) { + priv->def_counter[port] = MLX4_SINK_COUNTER_INDEX(dev); + mlx4_warn(dev, "can't allocate counter from old PF driver, using index %d\n", + MLX4_SINK_COUNTER_INDEX(dev)); + err = 0; } else { mlx4_err(dev, "%s: failed to allocate default counter port %d err %d\n", __func__, port + 1, err); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index 33669c29b341..753ea8bad953 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c @@ -1415,7 +1415,7 @@ static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter) if (fw->size & 0xF) { addr = dest + size; for (i = 0; i < (fw->size & 0xF); i++) - data[i] = temp[size + i]; + data[i] = ((u8 *)temp)[size + i]; for (; i < 16; i++) data[i] = 0; ret = qlcnic_ms_mem_write128(adapter, addr, diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index fd9745714d90..78849dd4ef8e 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -228,9 +228,7 @@ static void ravb_ring_format(struct net_device *ndev, int q) struct ravb_desc *desc = NULL; int rx_ring_size = sizeof(*rx_desc) * priv->num_rx_ring[q]; int tx_ring_size = sizeof(*tx_desc) * priv->num_tx_ring[q]; - struct sk_buff *skb; dma_addr_t dma_addr; - void *buffer; int i; priv->cur_rx[q] = 0; @@ -241,41 +239,28 @@ static void ravb_ring_format(struct net_device *ndev, int q) memset(priv->rx_ring[q], 0, rx_ring_size); /* Build RX ring buffer */ for (i = 0; i < priv->num_rx_ring[q]; i++) { - priv->rx_skb[q][i] = NULL; - skb = netdev_alloc_skb(ndev, PKT_BUF_SZ + RAVB_ALIGN - 1); - if (!skb) - break; - ravb_set_buffer_align(skb); /* RX descriptor */ rx_desc = &priv->rx_ring[q][i]; /* The size of the buffer should be on 16-byte boundary. */ rx_desc->ds_cc = cpu_to_le16(ALIGN(PKT_BUF_SZ, 16)); - dma_addr = dma_map_single(&ndev->dev, skb->data, + dma_addr = dma_map_single(&ndev->dev, priv->rx_skb[q][i]->data, ALIGN(PKT_BUF_SZ, 16), DMA_FROM_DEVICE); - if (dma_mapping_error(&ndev->dev, dma_addr)) { - dev_kfree_skb(skb); - break; - } - priv->rx_skb[q][i] = skb; + /* We just set the data size to 0 for a failed mapping which + * should prevent DMA from happening... + */ + if (dma_mapping_error(&ndev->dev, dma_addr)) + rx_desc->ds_cc = cpu_to_le16(0); rx_desc->dptr = cpu_to_le32(dma_addr); rx_desc->die_dt = DT_FEMPTY; } rx_desc = &priv->rx_ring[q][i]; rx_desc->dptr = cpu_to_le32((u32)priv->rx_desc_dma[q]); rx_desc->die_dt = DT_LINKFIX; /* type */ - priv->dirty_rx[q] = (u32)(i - priv->num_rx_ring[q]); memset(priv->tx_ring[q], 0, tx_ring_size); /* Build TX ring buffer */ for (i = 0; i < priv->num_tx_ring[q]; i++) { - priv->tx_skb[q][i] = NULL; - priv->tx_buffers[q][i] = NULL; - buffer = kmalloc(PKT_BUF_SZ + RAVB_ALIGN - 1, GFP_KERNEL); - if (!buffer) - break; - /* Aligned TX buffer */ - priv->tx_buffers[q][i] = buffer; tx_desc = &priv->tx_ring[q][i]; tx_desc->die_dt = DT_EEMPTY; } @@ -298,7 +283,10 @@ static void ravb_ring_format(struct net_device *ndev, int q) static int ravb_ring_init(struct net_device *ndev, int q) { struct ravb_private *priv = netdev_priv(ndev); + struct sk_buff *skb; int ring_size; + void *buffer; + int i; /* Allocate RX and TX skb rings */ priv->rx_skb[q] = kcalloc(priv->num_rx_ring[q], @@ -308,12 +296,28 @@ static int ravb_ring_init(struct net_device *ndev, int q) if (!priv->rx_skb[q] || !priv->tx_skb[q]) goto error; + for (i = 0; i < priv->num_rx_ring[q]; i++) { + skb = netdev_alloc_skb(ndev, PKT_BUF_SZ + RAVB_ALIGN - 1); + if (!skb) + goto error; + ravb_set_buffer_align(skb); + priv->rx_skb[q][i] = skb; + } + /* Allocate rings for the aligned buffers */ priv->tx_buffers[q] = kcalloc(priv->num_tx_ring[q], sizeof(*priv->tx_buffers[q]), GFP_KERNEL); if (!priv->tx_buffers[q]) goto error; + for (i = 0; i < priv->num_tx_ring[q]; i++) { + buffer = kmalloc(PKT_BUF_SZ + RAVB_ALIGN - 1, GFP_KERNEL); + if (!buffer) + goto error; + /* Aligned TX buffer */ + priv->tx_buffers[q][i] = buffer; + } + /* Allocate all RX descriptors. */ ring_size = sizeof(struct ravb_ex_rx_desc) * (priv->num_rx_ring[q] + 1); priv->rx_ring[q] = dma_alloc_coherent(NULL, ring_size, @@ -524,6 +528,10 @@ static bool ravb_rx(struct net_device *ndev, int *quota, int q) if (--boguscnt < 0) break; + /* We use 0-byte descriptors to mark the DMA mapping errors */ + if (!pkt_len) + continue; + if (desc_status & MSC_MC) stats->multicast++; @@ -543,10 +551,9 @@ static bool ravb_rx(struct net_device *ndev, int *quota, int q) skb = priv->rx_skb[q][entry]; priv->rx_skb[q][entry] = NULL; - dma_sync_single_for_cpu(&ndev->dev, - le32_to_cpu(desc->dptr), - ALIGN(PKT_BUF_SZ, 16), - DMA_FROM_DEVICE); + dma_unmap_single(&ndev->dev, le32_to_cpu(desc->dptr), + ALIGN(PKT_BUF_SZ, 16), + DMA_FROM_DEVICE); get_ts &= (q == RAVB_NC) ? RAVB_RXTSTAMP_TYPE_V2_L2_EVENT : ~RAVB_RXTSTAMP_TYPE_V2_L2_EVENT; @@ -584,17 +591,15 @@ static bool ravb_rx(struct net_device *ndev, int *quota, int q) if (!skb) break; /* Better luck next round. */ ravb_set_buffer_align(skb); - dma_unmap_single(&ndev->dev, le32_to_cpu(desc->dptr), - ALIGN(PKT_BUF_SZ, 16), - DMA_FROM_DEVICE); dma_addr = dma_map_single(&ndev->dev, skb->data, le16_to_cpu(desc->ds_cc), DMA_FROM_DEVICE); skb_checksum_none_assert(skb); - if (dma_mapping_error(&ndev->dev, dma_addr)) { - dev_kfree_skb_any(skb); - break; - } + /* We just set the data size to 0 for a failed mapping + * which should prevent DMA from happening... + */ + if (dma_mapping_error(&ndev->dev, dma_addr)) + desc->ds_cc = cpu_to_le16(0); desc->dptr = cpu_to_le32(dma_addr); priv->rx_skb[q][entry] = skb; } @@ -1279,7 +1284,6 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev) u32 dma_addr; void *buffer; u32 entry; - u32 tccr; spin_lock_irqsave(&priv->lock, flags); if (priv->cur_tx[q] - priv->dirty_tx[q] >= priv->num_tx_ring[q]) { @@ -1328,9 +1332,7 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev) dma_wmb(); desc->die_dt = DT_FSINGLE; - tccr = ravb_read(ndev, TCCR); - if (!(tccr & (TCCR_TSRQ0 << q))) - ravb_write(ndev, tccr | (TCCR_TSRQ0 << q), TCCR); + ravb_write(ndev, ravb_read(ndev, TCCR) | (TCCR_TSRQ0 << q), TCCR); priv->cur_tx[q]++; if (priv->cur_tx[q] - priv->dirty_tx[q] >= priv->num_tx_ring[q] && diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 847643455468..605cc8948594 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -101,6 +101,11 @@ static unsigned int efx_ef10_mem_map_size(struct efx_nic *efx) return resource_size(&efx->pci_dev->resource[bar]); } +static bool efx_ef10_is_vf(struct efx_nic *efx) +{ + return efx->type->is_vf; +} + static int efx_ef10_get_pf_index(struct efx_nic *efx) { MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_FUNCTION_INFO_OUT_LEN); @@ -677,6 +682,48 @@ static int efx_ef10_probe_pf(struct efx_nic *efx) return efx_ef10_probe(efx); } +int efx_ef10_vadaptor_alloc(struct efx_nic *efx, unsigned int port_id) +{ + MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_ALLOC_IN_LEN); + + MCDI_SET_DWORD(inbuf, VADAPTOR_ALLOC_IN_UPSTREAM_PORT_ID, port_id); + return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_ALLOC, inbuf, sizeof(inbuf), + NULL, 0, NULL); +} + +int efx_ef10_vadaptor_free(struct efx_nic *efx, unsigned int port_id) +{ + MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_FREE_IN_LEN); + + MCDI_SET_DWORD(inbuf, VADAPTOR_FREE_IN_UPSTREAM_PORT_ID, port_id); + return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_FREE, inbuf, sizeof(inbuf), + NULL, 0, NULL); +} + +int efx_ef10_vport_add_mac(struct efx_nic *efx, + unsigned int port_id, u8 *mac) +{ + MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_ADD_MAC_ADDRESS_IN_LEN); + + MCDI_SET_DWORD(inbuf, VPORT_ADD_MAC_ADDRESS_IN_VPORT_ID, port_id); + ether_addr_copy(MCDI_PTR(inbuf, VPORT_ADD_MAC_ADDRESS_IN_MACADDR), mac); + + return efx_mcdi_rpc(efx, MC_CMD_VPORT_ADD_MAC_ADDRESS, inbuf, + sizeof(inbuf), NULL, 0, NULL); +} + +int efx_ef10_vport_del_mac(struct efx_nic *efx, + unsigned int port_id, u8 *mac) +{ + MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN); + + MCDI_SET_DWORD(inbuf, VPORT_DEL_MAC_ADDRESS_IN_VPORT_ID, port_id); + ether_addr_copy(MCDI_PTR(inbuf, VPORT_DEL_MAC_ADDRESS_IN_MACADDR), mac); + + return efx_mcdi_rpc(efx, MC_CMD_VPORT_DEL_MAC_ADDRESS, inbuf, + sizeof(inbuf), NULL, 0, NULL); +} + #ifdef CONFIG_SFC_SRIOV static int efx_ef10_probe_vf(struct efx_nic *efx) { @@ -3804,6 +3851,72 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx) WARN_ON(remove_failed); } +static int efx_ef10_vport_set_mac_address(struct efx_nic *efx) +{ + struct efx_ef10_nic_data *nic_data = efx->nic_data; + u8 mac_old[ETH_ALEN]; + int rc, rc2; + + /* Only reconfigure a PF-created vport */ + if (is_zero_ether_addr(nic_data->vport_mac)) + return 0; + + efx_device_detach_sync(efx); + efx_net_stop(efx->net_dev); + down_write(&efx->filter_sem); + efx_ef10_filter_table_remove(efx); + up_write(&efx->filter_sem); + + rc = efx_ef10_vadaptor_free(efx, nic_data->vport_id); + if (rc) + goto restore_filters; + + ether_addr_copy(mac_old, nic_data->vport_mac); + rc = efx_ef10_vport_del_mac(efx, nic_data->vport_id, + nic_data->vport_mac); + if (rc) + goto restore_vadaptor; + + rc = efx_ef10_vport_add_mac(efx, nic_data->vport_id, + efx->net_dev->dev_addr); + if (!rc) { + ether_addr_copy(nic_data->vport_mac, efx->net_dev->dev_addr); + } else { + rc2 = efx_ef10_vport_add_mac(efx, nic_data->vport_id, mac_old); + if (rc2) { + /* Failed to add original MAC, so clear vport_mac */ + eth_zero_addr(nic_data->vport_mac); + goto reset_nic; + } + } + +restore_vadaptor: + rc2 = efx_ef10_vadaptor_alloc(efx, nic_data->vport_id); + if (rc2) + goto reset_nic; +restore_filters: + down_write(&efx->filter_sem); + rc2 = efx_ef10_filter_table_probe(efx); + up_write(&efx->filter_sem); + if (rc2) + goto reset_nic; + + rc2 = efx_net_open(efx->net_dev); + if (rc2) + goto reset_nic; + + netif_device_attach(efx->net_dev); + + return rc; + +reset_nic: + netif_err(efx, drv, efx->net_dev, + "Failed to restore when changing MAC address - scheduling reset\n"); + efx_schedule_reset(efx, RESET_TYPE_DATAPATH); + + return rc ? rc : rc2; +} + static int efx_ef10_set_mac_address(struct efx_nic *efx) { MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_SET_MAC_IN_LEN); @@ -3820,8 +3933,8 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx) efx->net_dev->dev_addr); MCDI_SET_DWORD(inbuf, VADAPTOR_SET_MAC_IN_UPSTREAM_PORT_ID, nic_data->vport_id); - rc = efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_SET_MAC, inbuf, - sizeof(inbuf), NULL, 0, NULL); + rc = efx_mcdi_rpc_quiet(efx, MC_CMD_VADAPTOR_SET_MAC, inbuf, + sizeof(inbuf), NULL, 0, NULL); efx_ef10_filter_table_probe(efx); up_write(&efx->filter_sem); @@ -3829,38 +3942,27 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx) efx_net_open(efx->net_dev); netif_device_attach(efx->net_dev); -#if !defined(CONFIG_SFC_SRIOV) - if (rc == -EPERM) - netif_err(efx, drv, efx->net_dev, - "Cannot change MAC address; use sfboot to enable mac-spoofing" - " on this interface\n"); -#else - if (rc == -EPERM) { +#ifdef CONFIG_SFC_SRIOV + if (efx->pci_dev->is_virtfn && efx->pci_dev->physfn) { struct pci_dev *pci_dev_pf = efx->pci_dev->physfn; - /* Switch to PF and change MAC address on vport */ - if (efx->pci_dev->is_virtfn && pci_dev_pf) { - struct efx_nic *efx_pf = pci_get_drvdata(pci_dev_pf); + if (rc == -EPERM) { + struct efx_nic *efx_pf; - if (!efx_ef10_sriov_set_vf_mac(efx_pf, - nic_data->vf_index, - efx->net_dev->dev_addr)) - return 0; - } - netif_err(efx, drv, efx->net_dev, - "Cannot change MAC address; use sfboot to enable mac-spoofing" - " on this interface\n"); - } else if (efx->pci_dev->is_virtfn) { - /* Successfully changed by VF (with MAC spoofing), so update the - * parent PF if possible. - */ - struct pci_dev *pci_dev_pf = efx->pci_dev->physfn; + /* Switch to PF and change MAC address on vport */ + efx_pf = pci_get_drvdata(pci_dev_pf); - if (pci_dev_pf) { + rc = efx_ef10_sriov_set_vf_mac(efx_pf, + nic_data->vf_index, + efx->net_dev->dev_addr); + } else if (!rc) { struct efx_nic *efx_pf = pci_get_drvdata(pci_dev_pf); struct efx_ef10_nic_data *nic_data = efx_pf->nic_data; unsigned int i; + /* MAC address successfully changed by VF (with MAC + * spoofing) so update the parent PF if possible. + */ for (i = 0; i < efx_pf->vf_count; ++i) { struct ef10_vf *vf = nic_data->vf + i; @@ -3871,8 +3973,24 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx) } } } - } + } else #endif + if (rc == -EPERM) { + netif_err(efx, drv, efx->net_dev, + "Cannot change MAC address; use sfboot to enable" + " mac-spoofing on this interface\n"); + } else if (rc == -ENOSYS && !efx_ef10_is_vf(efx)) { + /* If the active MCFW does not support MC_CMD_VADAPTOR_SET_MAC + * fall-back to the method of changing the MAC address on the + * vport. This only applies to PFs because such versions of + * MCFW do not support VFs. + */ + rc = efx_ef10_vport_set_mac_address(efx); + } else { + efx_mcdi_display_error(efx, MC_CMD_VADAPTOR_SET_MAC, + sizeof(inbuf), NULL, 0, rc); + } + return rc; } diff --git a/drivers/net/ethernet/sfc/ef10_sriov.c b/drivers/net/ethernet/sfc/ef10_sriov.c index 6c9b6e45509a..3c17f274e802 100644 --- a/drivers/net/ethernet/sfc/ef10_sriov.c +++ b/drivers/net/ethernet/sfc/ef10_sriov.c @@ -29,30 +29,6 @@ static int efx_ef10_evb_port_assign(struct efx_nic *efx, unsigned int port_id, NULL, 0, NULL); } -static int efx_ef10_vport_add_mac(struct efx_nic *efx, - unsigned int port_id, u8 *mac) -{ - MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_ADD_MAC_ADDRESS_IN_LEN); - - MCDI_SET_DWORD(inbuf, VPORT_ADD_MAC_ADDRESS_IN_VPORT_ID, port_id); - ether_addr_copy(MCDI_PTR(inbuf, VPORT_ADD_MAC_ADDRESS_IN_MACADDR), mac); - - return efx_mcdi_rpc(efx, MC_CMD_VPORT_ADD_MAC_ADDRESS, inbuf, - sizeof(inbuf), NULL, 0, NULL); -} - -static int efx_ef10_vport_del_mac(struct efx_nic *efx, - unsigned int port_id, u8 *mac) -{ - MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN); - - MCDI_SET_DWORD(inbuf, VPORT_DEL_MAC_ADDRESS_IN_VPORT_ID, port_id); - ether_addr_copy(MCDI_PTR(inbuf, VPORT_DEL_MAC_ADDRESS_IN_MACADDR), mac); - - return efx_mcdi_rpc(efx, MC_CMD_VPORT_DEL_MAC_ADDRESS, inbuf, - sizeof(inbuf), NULL, 0, NULL); -} - static int efx_ef10_vswitch_alloc(struct efx_nic *efx, unsigned int port_id, unsigned int vswitch_type) { @@ -136,24 +112,6 @@ static int efx_ef10_vport_free(struct efx_nic *efx, unsigned int port_id) NULL, 0, NULL); } -static int efx_ef10_vadaptor_alloc(struct efx_nic *efx, unsigned int port_id) -{ - MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_ALLOC_IN_LEN); - - MCDI_SET_DWORD(inbuf, VADAPTOR_ALLOC_IN_UPSTREAM_PORT_ID, port_id); - return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_ALLOC, inbuf, sizeof(inbuf), - NULL, 0, NULL); -} - -static int efx_ef10_vadaptor_free(struct efx_nic *efx, unsigned int port_id) -{ - MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_FREE_IN_LEN); - - MCDI_SET_DWORD(inbuf, VADAPTOR_FREE_IN_UPSTREAM_PORT_ID, port_id); - return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_FREE, inbuf, sizeof(inbuf), - NULL, 0, NULL); -} - static void efx_ef10_sriov_free_vf_vports(struct efx_nic *efx) { struct efx_ef10_nic_data *nic_data = efx->nic_data; @@ -640,21 +598,21 @@ int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf_i, u16 vlan, MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL, vf->vlan, &vf->vport_id); if (rc) - goto reset_nic; + goto reset_nic_up_write; restore_mac: if (!is_zero_ether_addr(vf->mac)) { rc2 = efx_ef10_vport_add_mac(efx, vf->vport_id, vf->mac); if (rc2) { eth_zero_addr(vf->mac); - goto reset_nic; + goto reset_nic_up_write; } } restore_evb_port: rc2 = efx_ef10_evb_port_assign(efx, vf->vport_id, vf_i); if (rc2) - goto reset_nic; + goto reset_nic_up_write; else vf->vport_assigned = 1; @@ -662,14 +620,16 @@ restore_vadaptor: if (vf->efx) { rc2 = efx_ef10_vadaptor_alloc(vf->efx, EVB_PORT_ID_ASSIGNED); if (rc2) - goto reset_nic; + goto reset_nic_up_write; } restore_filters: if (vf->efx) { rc2 = vf->efx->type->filter_table_probe(vf->efx); if (rc2) - goto reset_nic; + goto reset_nic_up_write; + + up_write(&vf->efx->filter_sem); up_write(&vf->efx->filter_sem); @@ -681,9 +641,12 @@ restore_filters: } return rc; +reset_nic_up_write: + if (vf->efx) + up_write(&vf->efx->filter_sem); + reset_nic: if (vf->efx) { - up_write(&vf->efx->filter_sem); netif_err(efx, drv, efx->net_dev, "Failed to restore VF - scheduling reset.\n"); efx_schedule_reset(vf->efx, RESET_TYPE_DATAPATH); diff --git a/drivers/net/ethernet/sfc/ef10_sriov.h b/drivers/net/ethernet/sfc/ef10_sriov.h index db4ef537c610..6d25b92cb45e 100644 --- a/drivers/net/ethernet/sfc/ef10_sriov.h +++ b/drivers/net/ethernet/sfc/ef10_sriov.h @@ -65,5 +65,11 @@ int efx_ef10_vswitching_restore_pf(struct efx_nic *efx); int efx_ef10_vswitching_restore_vf(struct efx_nic *efx); void efx_ef10_vswitching_remove_pf(struct efx_nic *efx); void efx_ef10_vswitching_remove_vf(struct efx_nic *efx); +int efx_ef10_vport_add_mac(struct efx_nic *efx, + unsigned int port_id, u8 *mac); +int efx_ef10_vport_del_mac(struct efx_nic *efx, + unsigned int port_id, u8 *mac); +int efx_ef10_vadaptor_alloc(struct efx_nic *efx, unsigned int port_id); +int efx_ef10_vadaptor_free(struct efx_nic *efx, unsigned int port_id); #endif /* EF10_SRIOV_H */ diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 804b9ad553d3..03bc03b67f08 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -245,11 +245,17 @@ static int efx_check_disabled(struct efx_nic *efx) */ static int efx_process_channel(struct efx_channel *channel, int budget) { + struct efx_tx_queue *tx_queue; int spent; if (unlikely(!channel->enabled)) return 0; + efx_for_each_channel_tx_queue(tx_queue, channel) { + tx_queue->pkts_compl = 0; + tx_queue->bytes_compl = 0; + } + spent = efx_nic_process_eventq(channel, budget); if (spent && efx_channel_has_rx_queue(channel)) { struct efx_rx_queue *rx_queue = @@ -259,6 +265,14 @@ static int efx_process_channel(struct efx_channel *channel, int budget) efx_fast_push_rx_descriptors(rx_queue, true); } + /* Update BQL */ + efx_for_each_channel_tx_queue(tx_queue, channel) { + if (tx_queue->bytes_compl) { + netdev_tx_completed_queue(tx_queue->core_txq, + tx_queue->pkts_compl, tx_queue->bytes_compl); + } + } + return spent; } diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index d72f522bf9c3..47d1e3a96522 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -241,6 +241,8 @@ struct efx_tx_queue { unsigned int read_count ____cacheline_aligned_in_smp; unsigned int old_write_count; unsigned int merge_events; + unsigned int bytes_compl; + unsigned int pkts_compl; /* Members used only on the xmit path */ unsigned int insert_count ____cacheline_aligned_in_smp; diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c index aaf2987512b5..1833a0146571 100644 --- a/drivers/net/ethernet/sfc/tx.c +++ b/drivers/net/ethernet/sfc/tx.c @@ -617,7 +617,8 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index) EFX_BUG_ON_PARANOID(index > tx_queue->ptr_mask); efx_dequeue_buffers(tx_queue, index, &pkts_compl, &bytes_compl); - netdev_tx_completed_queue(tx_queue->core_txq, pkts_compl, bytes_compl); + tx_queue->pkts_compl += pkts_compl; + tx_queue->bytes_compl += bytes_compl; if (pkts_compl > 1) ++tx_queue->merge_events; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 50f7a7a26821..864b476f7fd5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -2843,7 +2843,7 @@ int stmmac_dvr_probe(struct device *device, if (res->mac) memcpy(priv->dev->dev_addr, res->mac, ETH_ALEN); - dev_set_drvdata(device, priv); + dev_set_drvdata(device, priv->dev); /* Verify driver arguments */ stmmac_verify_args(); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index f3918c7e7eeb..bcdc8955c719 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -413,3 +413,7 @@ static int stmmac_pltfr_resume(struct device *dev) SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops, stmmac_pltfr_suspend, stmmac_pltfr_resume); EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops); + +MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet platform support"); +MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c index 0c5842aeb807..ab6051a43134 100644 --- a/drivers/net/ethernet/sun/niu.c +++ b/drivers/net/ethernet/sun/niu.c @@ -6658,10 +6658,8 @@ static netdev_tx_t niu_start_xmit(struct sk_buff *skb, struct sk_buff *skb_new; skb_new = skb_realloc_headroom(skb, len); - if (!skb_new) { - rp->tx_errors++; + if (!skb_new) goto out_drop; - } kfree_skb(skb); skb = skb_new; } else diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 462820514fae..d155bf2573cd 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -138,19 +138,6 @@ do { \ #define CPSW_CMINTMAX_INTVL (1000 / CPSW_CMINTMIN_CNT) #define CPSW_CMINTMIN_INTVL ((1000 / CPSW_CMINTMAX_CNT) + 1) -#define cpsw_enable_irq(priv) \ - do { \ - u32 i; \ - for (i = 0; i < priv->num_irqs; i++) \ - enable_irq(priv->irqs_table[i]); \ - } while (0) -#define cpsw_disable_irq(priv) \ - do { \ - u32 i; \ - for (i = 0; i < priv->num_irqs; i++) \ - disable_irq_nosync(priv->irqs_table[i]); \ - } while (0) - #define cpsw_slave_index(priv) \ ((priv->data.dual_emac) ? priv->emac_port : \ priv->data.active_slave) @@ -509,9 +496,11 @@ static const struct cpsw_stats cpsw_gstrings_stats[] = { (func)(slave++, ##arg); \ } while (0) #define cpsw_get_slave_ndev(priv, __slave_no__) \ - (priv->slaves[__slave_no__].ndev) + ((__slave_no__ < priv->data.slaves) ? \ + priv->slaves[__slave_no__].ndev : NULL) #define cpsw_get_slave_priv(priv, __slave_no__) \ - ((priv->slaves[__slave_no__].ndev) ? \ + (((__slave_no__ < priv->data.slaves) && \ + (priv->slaves[__slave_no__].ndev)) ? \ netdev_priv(priv->slaves[__slave_no__].ndev) : NULL) \ #define cpsw_dual_emac_src_port_detect(status, priv, ndev, skb) \ @@ -781,7 +770,7 @@ static irqreturn_t cpsw_rx_interrupt(int irq, void *dev_id) cpsw_intr_disable(priv); if (priv->irq_enabled == true) { - cpsw_disable_irq(priv); + disable_irq_nosync(priv->irqs_table[0]); priv->irq_enabled = false; } @@ -804,9 +793,7 @@ static irqreturn_t cpsw_rx_interrupt(int irq, void *dev_id) static int cpsw_poll(struct napi_struct *napi, int budget) { struct cpsw_priv *priv = napi_to_priv(napi); - int num_tx, num_rx; - - num_tx = cpdma_chan_process(priv->txch, 128); + int num_rx; num_rx = cpdma_chan_process(priv->rxch, budget); if (num_rx < budget) { @@ -817,13 +804,12 @@ static int cpsw_poll(struct napi_struct *napi, int budget) prim_cpsw = cpsw_get_slave_priv(priv, 0); if (prim_cpsw->irq_enabled == false) { prim_cpsw->irq_enabled = true; - cpsw_enable_irq(priv); + enable_irq(priv->irqs_table[0]); } } - if (num_rx || num_tx) - cpsw_dbg(priv, intr, "poll %d rx, %d tx pkts\n", - num_rx, num_tx); + if (num_rx) + cpsw_dbg(priv, intr, "poll %d rx pkts\n", num_rx); return num_rx; } @@ -1333,7 +1319,7 @@ static int cpsw_ndo_open(struct net_device *ndev) if (prim_cpsw->irq_enabled == false) { if ((priv == prim_cpsw) || !netif_running(prim_cpsw->ndev)) { prim_cpsw->irq_enabled = true; - cpsw_enable_irq(prim_cpsw); + enable_irq(prim_cpsw->irqs_table[0]); } } diff --git a/drivers/net/ethernet/ti/netcp.h b/drivers/net/ethernet/ti/netcp.h index bbacf5cccec2..a8a730641bbb 100644 --- a/drivers/net/ethernet/ti/netcp.h +++ b/drivers/net/ethernet/ti/netcp.h @@ -223,6 +223,7 @@ void *netcp_device_find_module(struct netcp_device *netcp_device, /* SGMII functions */ int netcp_sgmii_reset(void __iomem *sgmii_ofs, int port); +bool netcp_sgmii_rtreset(void __iomem *sgmii_ofs, int port, bool set); int netcp_sgmii_get_port_link(void __iomem *sgmii_ofs, int port); int netcp_sgmii_config(void __iomem *sgmii_ofs, int port, u32 interface); diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c index 5ec4ed3f6c8d..9749dfd78c43 100644 --- a/drivers/net/ethernet/ti/netcp_core.c +++ b/drivers/net/ethernet/ti/netcp_core.c @@ -1617,11 +1617,11 @@ static int netcp_ndo_open(struct net_device *ndev) } mutex_unlock(&netcp_modules_lock); - netcp_rxpool_refill(netcp); napi_enable(&netcp->rx_napi); napi_enable(&netcp->tx_napi); knav_queue_enable_notify(netcp->tx_compl_q); knav_queue_enable_notify(netcp->rx_queue); + netcp_rxpool_refill(netcp); netif_tx_wake_all_queues(ndev); dev_dbg(netcp->ndev_dev, "netcp device %s opened\n", ndev->name); return 0; @@ -2112,6 +2112,7 @@ probe_quit: static int netcp_remove(struct platform_device *pdev) { struct netcp_device *netcp_device = platform_get_drvdata(pdev); + struct netcp_intf *netcp_intf, *netcp_tmp; struct netcp_inst_modpriv *inst_modpriv, *tmp; struct netcp_module *module; @@ -2123,10 +2124,17 @@ static int netcp_remove(struct platform_device *pdev) list_del(&inst_modpriv->inst_list); kfree(inst_modpriv); } - WARN(!list_empty(&netcp_device->interface_head), "%s interface list not empty!\n", - pdev->name); - devm_kfree(&pdev->dev, netcp_device); + /* now that all modules are removed, clean up the interfaces */ + list_for_each_entry_safe(netcp_intf, netcp_tmp, + &netcp_device->interface_head, + interface_list) { + netcp_delete_interface(netcp_device, netcp_intf->ndev); + } + + WARN(!list_empty(&netcp_device->interface_head), + "%s interface list not empty!\n", pdev->name); + pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); platform_set_drvdata(pdev, NULL); diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index 9b7e0a34c98b..1974a8ae764a 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -1901,11 +1901,28 @@ static void gbe_port_config(struct gbe_priv *gbe_dev, struct gbe_slave *slave, writel(slave->mac_control, GBE_REG_ADDR(slave, emac_regs, mac_control)); } +static void gbe_sgmii_rtreset(struct gbe_priv *priv, + struct gbe_slave *slave, bool set) +{ + void __iomem *sgmii_port_regs; + + if (SLAVE_LINK_IS_XGMII(slave)) + return; + + if ((priv->ss_version == GBE_SS_VERSION_14) && (slave->slave_num >= 2)) + sgmii_port_regs = priv->sgmii_port34_regs; + else + sgmii_port_regs = priv->sgmii_port_regs; + + netcp_sgmii_rtreset(sgmii_port_regs, slave->slave_num, set); +} + static void gbe_slave_stop(struct gbe_intf *intf) { struct gbe_priv *gbe_dev = intf->gbe_dev; struct gbe_slave *slave = intf->slave; + gbe_sgmii_rtreset(gbe_dev, slave, true); gbe_port_reset(slave); /* Disable forwarding */ cpsw_ale_control_set(gbe_dev->ale, slave->port_num, @@ -1947,6 +1964,7 @@ static int gbe_slave_open(struct gbe_intf *gbe_intf) gbe_sgmii_config(priv, slave); gbe_port_reset(slave); + gbe_sgmii_rtreset(priv, slave, false); gbe_port_config(priv, slave, priv->rx_packet_max); gbe_set_slave_mac(slave, gbe_intf); /* enable forwarding */ @@ -2490,10 +2508,9 @@ static void free_secondary_ports(struct gbe_priv *gbe_dev) { struct gbe_slave *slave; - for (;;) { + while (!list_empty(&gbe_dev->secondary_slaves)) { slave = first_sec_slave(gbe_dev); - if (!slave) - break; + if (slave->phy) phy_disconnect(slave->phy); list_del(&slave->slave_list); @@ -2839,14 +2856,13 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev, &gbe_dev->dma_chan_name); if (ret < 0) { dev_err(dev, "missing \"tx-channel\" parameter\n"); - ret = -ENODEV; - goto quit; + return -EINVAL; } if (!strcmp(node->name, "gbe")) { ret = get_gbe_resource_version(gbe_dev, node); if (ret) - goto quit; + return ret; dev_dbg(dev, "ss_version: 0x%08x\n", gbe_dev->ss_version); @@ -2857,22 +2873,20 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev, else ret = -ENODEV; - if (ret) - goto quit; } else if (!strcmp(node->name, "xgbe")) { ret = set_xgbe_ethss10_priv(gbe_dev, node); if (ret) - goto quit; + return ret; ret = netcp_xgbe_serdes_init(gbe_dev->xgbe_serdes_regs, gbe_dev->ss_regs); - if (ret) - goto quit; } else { dev_err(dev, "unknown GBE node(%s)\n", node->name); ret = -ENODEV; - goto quit; } + if (ret) + return ret; + interfaces = of_get_child_by_name(node, "interfaces"); if (!interfaces) dev_err(dev, "could not find interfaces\n"); @@ -2880,11 +2894,11 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev, ret = netcp_txpipe_init(&gbe_dev->tx_pipe, netcp_device, gbe_dev->dma_chan_name, gbe_dev->tx_queue_id); if (ret) - goto quit; + return ret; ret = netcp_txpipe_open(&gbe_dev->tx_pipe); if (ret) - goto quit; + return ret; /* Create network interfaces */ INIT_LIST_HEAD(&gbe_dev->gbe_intf_head); @@ -2899,6 +2913,7 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev, if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves) break; } + of_node_put(interfaces); if (!gbe_dev->num_slaves) dev_warn(dev, "No network interface configured\n"); @@ -2911,9 +2926,10 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev, of_node_put(secondary_ports); if (!gbe_dev->num_slaves) { - dev_err(dev, "No network interface or secondary ports configured\n"); + dev_err(dev, + "No network interface or secondary ports configured\n"); ret = -ENODEV; - goto quit; + goto free_sec_ports; } memset(&ale_params, 0, sizeof(ale_params)); @@ -2927,7 +2943,7 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev, if (!gbe_dev->ale) { dev_err(gbe_dev->dev, "error initializing ale engine\n"); ret = -ENODEV; - goto quit; + goto free_sec_ports; } else { dev_dbg(gbe_dev->dev, "Created a gbe ale engine\n"); } @@ -2943,14 +2959,8 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev, *inst_priv = gbe_dev; return 0; -quit: - if (gbe_dev->hw_stats) - devm_kfree(dev, gbe_dev->hw_stats); - cpsw_ale_destroy(gbe_dev->ale); - if (gbe_dev->ss_regs) - devm_iounmap(dev, gbe_dev->ss_regs); - of_node_put(interfaces); - devm_kfree(dev, gbe_dev); +free_sec_ports: + free_secondary_ports(gbe_dev); return ret; } @@ -3023,12 +3033,9 @@ static int gbe_remove(struct netcp_device *netcp_device, void *inst_priv) free_secondary_ports(gbe_dev); if (!list_empty(&gbe_dev->gbe_intf_head)) - dev_alert(gbe_dev->dev, "unreleased ethss interfaces present\n"); + dev_alert(gbe_dev->dev, + "unreleased ethss interfaces present\n"); - devm_kfree(gbe_dev->dev, gbe_dev->hw_stats); - devm_iounmap(gbe_dev->dev, gbe_dev->ss_regs); - memset(gbe_dev, 0x00, sizeof(*gbe_dev)); - devm_kfree(gbe_dev->dev, gbe_dev); return 0; } diff --git a/drivers/net/ethernet/ti/netcp_sgmii.c b/drivers/net/ethernet/ti/netcp_sgmii.c index dbeb14266e2f..5d8419f658d0 100644 --- a/drivers/net/ethernet/ti/netcp_sgmii.c +++ b/drivers/net/ethernet/ti/netcp_sgmii.c @@ -18,6 +18,9 @@ #include "netcp.h" +#define SGMII_SRESET_RESET BIT(0) +#define SGMII_SRESET_RTRESET BIT(1) + #define SGMII_REG_STATUS_LOCK BIT(4) #define SGMII_REG_STATUS_LINK BIT(0) #define SGMII_REG_STATUS_AUTONEG BIT(2) @@ -51,12 +54,35 @@ static void sgmii_write_reg_bit(void __iomem *base, int reg, u32 val) int netcp_sgmii_reset(void __iomem *sgmii_ofs, int port) { /* Soft reset */ - sgmii_write_reg_bit(sgmii_ofs, SGMII_SRESET_REG(port), 0x1); - while (sgmii_read_reg(sgmii_ofs, SGMII_SRESET_REG(port)) != 0x0) + sgmii_write_reg_bit(sgmii_ofs, SGMII_SRESET_REG(port), + SGMII_SRESET_RESET); + + while ((sgmii_read_reg(sgmii_ofs, SGMII_SRESET_REG(port)) & + SGMII_SRESET_RESET) != 0x0) ; + return 0; } +/* port is 0 based */ +bool netcp_sgmii_rtreset(void __iomem *sgmii_ofs, int port, bool set) +{ + u32 reg; + bool oldval; + + /* Initiate a soft reset */ + reg = sgmii_read_reg(sgmii_ofs, SGMII_SRESET_REG(port)); + oldval = (reg & SGMII_SRESET_RTRESET) != 0x0; + if (set) + reg |= SGMII_SRESET_RTRESET; + else + reg &= ~SGMII_SRESET_RTRESET; + sgmii_write_reg(sgmii_ofs, SGMII_SRESET_REG(port), reg); + wmb(); + + return oldval; +} + int netcp_sgmii_get_port_link(void __iomem *sgmii_ofs, int port) { u32 status = 0, link = 0; diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 4208dd7ef101..d95f9aae95e7 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -1530,9 +1530,9 @@ static int axienet_probe(struct platform_device *pdev) /* Map device registers */ ethres = platform_get_resource(pdev, IORESOURCE_MEM, 0); lp->regs = devm_ioremap_resource(&pdev->dev, ethres); - if (!lp->regs) { + if (IS_ERR(lp->regs)) { dev_err(&pdev->dev, "could not map Axi Ethernet regs.\n"); - ret = -ENOMEM; + ret = PTR_ERR(lp->regs); goto free_netdev; } @@ -1599,9 +1599,9 @@ static int axienet_probe(struct platform_device *pdev) goto free_netdev; } lp->dma_regs = devm_ioremap_resource(&pdev->dev, &dmares); - if (!lp->dma_regs) { + if (IS_ERR(lp->dma_regs)) { dev_err(&pdev->dev, "could not map DMA regs\n"); - ret = -ENOMEM; + ret = PTR_ERR(lp->dma_regs); goto free_netdev; } lp->rx_irq = irq_of_parse_and_map(np, 1); diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index 7856b6ccf5c5..d95a50ae996d 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -482,6 +482,7 @@ static void bpq_setup(struct net_device *dev) memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN); dev->flags = 0; + dev->features = NETIF_F_LLTX; /* Allow recursion */ #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) dev->header_ops = &ax25_header_ops; diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h index 953a97492fab..9542b7bac61a 100644 --- a/drivers/net/ipvlan/ipvlan.h +++ b/drivers/net/ipvlan/ipvlan.h @@ -67,8 +67,6 @@ struct ipvl_dev { struct ipvl_port *port; struct net_device *phy_dev; struct list_head addrs; - int ipv4cnt; - int ipv6cnt; struct ipvl_pcpu_stats __percpu *pcpu_stats; DECLARE_BITMAP(mac_filters, IPVLAN_MAC_FILTER_SIZE); netdev_features_t sfeatures; @@ -106,6 +104,11 @@ static inline struct ipvl_port *ipvlan_port_get_rcu(const struct net_device *d) return rcu_dereference(d->rx_handler_data); } +static inline struct ipvl_port *ipvlan_port_get_rcu_bh(const struct net_device *d) +{ + return rcu_dereference_bh(d->rx_handler_data); +} + static inline struct ipvl_port *ipvlan_port_get_rtnl(const struct net_device *d) { return rtnl_dereference(d->rx_handler_data); @@ -124,5 +127,5 @@ struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan, bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6); struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port, const void *iaddr, bool is_v6); -void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync); +void ipvlan_ht_addr_del(struct ipvl_addr *addr); #endif /* __IPVLAN_H */ diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index 8afbedad620d..207f62e8de9a 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c @@ -85,11 +85,9 @@ void ipvlan_ht_addr_add(struct ipvl_dev *ipvlan, struct ipvl_addr *addr) hlist_add_head_rcu(&addr->hlnode, &port->hlhead[hash]); } -void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync) +void ipvlan_ht_addr_del(struct ipvl_addr *addr) { hlist_del_init_rcu(&addr->hlnode); - if (sync) - synchronize_rcu(); } struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan, @@ -531,7 +529,7 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev) int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev) { struct ipvl_dev *ipvlan = netdev_priv(dev); - struct ipvl_port *port = ipvlan_port_get_rcu(ipvlan->phy_dev); + struct ipvl_port *port = ipvlan_port_get_rcu_bh(ipvlan->phy_dev); if (!port) goto out; diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index 1acc283160d9..20b58bdecf75 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -153,10 +153,9 @@ static int ipvlan_open(struct net_device *dev) else dev->flags &= ~IFF_NOARP; - if (ipvlan->ipv6cnt > 0 || ipvlan->ipv4cnt > 0) { - list_for_each_entry(addr, &ipvlan->addrs, anode) - ipvlan_ht_addr_add(ipvlan, addr); - } + list_for_each_entry(addr, &ipvlan->addrs, anode) + ipvlan_ht_addr_add(ipvlan, addr); + return dev_uc_add(phy_dev, phy_dev->dev_addr); } @@ -171,10 +170,9 @@ static int ipvlan_stop(struct net_device *dev) dev_uc_del(phy_dev, phy_dev->dev_addr); - if (ipvlan->ipv6cnt > 0 || ipvlan->ipv4cnt > 0) { - list_for_each_entry(addr, &ipvlan->addrs, anode) - ipvlan_ht_addr_del(addr, !dev->dismantle); - } + list_for_each_entry(addr, &ipvlan->addrs, anode) + ipvlan_ht_addr_del(addr); + return 0; } @@ -471,8 +469,6 @@ static int ipvlan_link_new(struct net *src_net, struct net_device *dev, ipvlan->port = port; ipvlan->sfeatures = IPVLAN_FEATURES; INIT_LIST_HEAD(&ipvlan->addrs); - ipvlan->ipv4cnt = 0; - ipvlan->ipv6cnt = 0; /* TODO Probably put random address here to be presented to the * world but keep using the physical-dev address for the outgoing @@ -508,12 +504,12 @@ static void ipvlan_link_delete(struct net_device *dev, struct list_head *head) struct ipvl_dev *ipvlan = netdev_priv(dev); struct ipvl_addr *addr, *next; - if (ipvlan->ipv6cnt > 0 || ipvlan->ipv4cnt > 0) { - list_for_each_entry_safe(addr, next, &ipvlan->addrs, anode) { - ipvlan_ht_addr_del(addr, !dev->dismantle); - list_del(&addr->anode); - } + list_for_each_entry_safe(addr, next, &ipvlan->addrs, anode) { + ipvlan_ht_addr_del(addr); + list_del(&addr->anode); + kfree_rcu(addr, rcu); } + list_del_rcu(&ipvlan->pnode); unregister_netdevice_queue(dev, head); netdev_upper_dev_unlink(ipvlan->phy_dev, dev); @@ -627,7 +623,7 @@ static int ipvlan_add_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr) memcpy(&addr->ip6addr, ip6_addr, sizeof(struct in6_addr)); addr->atype = IPVL_IPV6; list_add_tail(&addr->anode, &ipvlan->addrs); - ipvlan->ipv6cnt++; + /* If the interface is not up, the address will be added to the hash * list by ipvlan_open. */ @@ -645,10 +641,8 @@ static void ipvlan_del_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr) if (!addr) return; - ipvlan_ht_addr_del(addr, true); + ipvlan_ht_addr_del(addr); list_del(&addr->anode); - ipvlan->ipv6cnt--; - WARN_ON(ipvlan->ipv6cnt < 0); kfree_rcu(addr, rcu); return; @@ -661,6 +655,10 @@ static int ipvlan_addr6_event(struct notifier_block *unused, struct net_device *dev = (struct net_device *)if6->idev->dev; struct ipvl_dev *ipvlan = netdev_priv(dev); + /* FIXME IPv6 autoconf calls us from bh without RTNL */ + if (in_softirq()) + return NOTIFY_DONE; + if (!netif_is_ipvlan(dev)) return NOTIFY_DONE; @@ -699,7 +697,7 @@ static int ipvlan_add_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr) memcpy(&addr->ip4addr, ip4_addr, sizeof(struct in_addr)); addr->atype = IPVL_IPV4; list_add_tail(&addr->anode, &ipvlan->addrs); - ipvlan->ipv4cnt++; + /* If the interface is not up, the address will be added to the hash * list by ipvlan_open. */ @@ -717,10 +715,8 @@ static void ipvlan_del_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr) if (!addr) return; - ipvlan_ht_addr_del(addr, true); + ipvlan_ht_addr_del(addr); list_del(&addr->anode); - ipvlan->ipv4cnt--; - WARN_ON(ipvlan->ipv4cnt < 0); kfree_rcu(addr, rcu); return; diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index f8370808a018..edd77342773a 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -719,6 +719,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, struct virtio_net_hdr vnet_hdr = { 0 }; int vnet_hdr_len = 0; int copylen = 0; + int depth; bool zerocopy = false; size_t linear; ssize_t n; @@ -804,6 +805,12 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, skb_probe_transport_header(skb, ETH_HLEN); + /* Move network header to the right position for VLAN tagged packets */ + if ((skb->protocol == htons(ETH_P_8021Q) || + skb->protocol == htons(ETH_P_8021AD)) && + __vlan_get_protocol(skb, skb->protocol, &depth) != 0) + skb_set_network_header(skb, depth); + rcu_read_lock(); vlan = rcu_dereference(q->vlan); /* copy skb_ubuf_info for callback when skb has no error */ @@ -1355,6 +1362,7 @@ static void macvtap_exit(void) class_unregister(macvtap_class); cdev_del(&macvtap_cdev); unregister_chrdev_region(macvtap_major, MACVTAP_NUM_DEVS); + idr_destroy(&minor_idr); } module_exit(macvtap_exit); diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index cf18940f4e84..cb86d7a01542 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -191,7 +191,7 @@ config MDIO_BUS_MUX_GPIO config MDIO_BUS_MUX_MMIOREG tristate "Support for MMIO device-controlled MDIO bus multiplexers" - depends on OF_MDIO + depends on OF_MDIO && HAS_IOMEM select MDIO_BUS_MUX help This module provides a driver for MDIO bus multiplexers that diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index c7a12e2e07b7..8a3bf5469892 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -164,7 +164,7 @@ static int dp83867_config_init(struct phy_device *phydev) return ret; } - if ((phydev->interface >= PHY_INTERFACE_MODE_RGMII_ID) || + if ((phydev->interface >= PHY_INTERFACE_MODE_RGMII_ID) && (phydev->interface <= PHY_INTERFACE_MODE_RGMII_RXID)) { val = phy_read_mmd_indirect(phydev, DP83867_RGMIICTL, DP83867_DEVADDR, phydev->addr); diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 095ef3fe369a..46a14cbb0215 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -421,6 +421,8 @@ static int mdio_bus_match(struct device *dev, struct device_driver *drv) { struct phy_device *phydev = to_phy_device(dev); struct phy_driver *phydrv = to_phy_driver(drv); + const int num_ids = ARRAY_SIZE(phydev->c45_ids.device_ids); + int i; if (of_driver_match_device(dev, drv)) return 1; @@ -428,8 +430,21 @@ static int mdio_bus_match(struct device *dev, struct device_driver *drv) if (phydrv->match_phy_device) return phydrv->match_phy_device(phydev); - return (phydrv->phy_id & phydrv->phy_id_mask) == - (phydev->phy_id & phydrv->phy_id_mask); + if (phydev->is_c45) { + for (i = 1; i < num_ids; i++) { + if (!(phydev->c45_ids.devices_in_package & (1 << i))) + continue; + + if ((phydrv->phy_id & phydrv->phy_id_mask) == + (phydev->c45_ids.device_ids[i] & + phydrv->phy_id_mask)) + return 1; + } + return 0; + } else { + return (phydrv->phy_id & phydrv->phy_id_mask) == + (phydev->phy_id & phydrv->phy_id_mask); + } } #ifdef CONFIG_PM diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 4545e78840b0..35a2bffe848a 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -523,6 +523,7 @@ static const struct driver_info wwan_info = { #define REALTEK_VENDOR_ID 0x0bda #define SAMSUNG_VENDOR_ID 0x04e8 #define LENOVO_VENDOR_ID 0x17ef +#define NVIDIA_VENDOR_ID 0x0955 static const struct usb_device_id products[] = { /* BLACKLIST !! @@ -710,6 +711,13 @@ static const struct usb_device_id products[] = { .driver_info = 0, }, +/* NVIDIA Tegra USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ +{ + USB_DEVICE_AND_INTERFACE_INFO(NVIDIA_VENDOR_ID, 0x09ff, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, + /* WHITELIST!!! * * CDC Ether uses two interfaces, not necessarily consecutive. diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c index e4b7a47a825c..efc18e05af0a 100644 --- a/drivers/net/usb/cdc_mbim.c +++ b/drivers/net/usb/cdc_mbim.c @@ -158,7 +158,7 @@ static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf) if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting)) goto err; - ret = cdc_ncm_bind_common(dev, intf, data_altsetting); + ret = cdc_ncm_bind_common(dev, intf, data_altsetting, 0); if (ret) goto err; diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 8067b8fbb0ee..db40175b1a0b 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -6,7 +6,7 @@ * Original author: Hans Petter Selasky <hans.petter.selasky@stericsson.com> * * USB Host Driver for Network Control Model (NCM) - * http://www.usb.org/developers/devclass_docs/NCM10.zip + * http://www.usb.org/developers/docs/devclass_docs/NCM10_012011.zip * * The NCM encoding, decoding and initialization logic * derives from FreeBSD 8.x. if_cdce.c and if_cdcereg.h @@ -684,10 +684,12 @@ static void cdc_ncm_free(struct cdc_ncm_ctx *ctx) ctx->tx_curr_skb = NULL; } + kfree(ctx->delayed_ndp16); + kfree(ctx); } -int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting) +int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting, int drvflags) { const struct usb_cdc_union_desc *union_desc = NULL; struct cdc_ncm_ctx *ctx; @@ -855,6 +857,17 @@ advance: /* finish setting up the device specific data */ cdc_ncm_setup(dev); + /* Device-specific flags */ + ctx->drvflags = drvflags; + + /* Allocate the delayed NDP if needed. */ + if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) { + ctx->delayed_ndp16 = kzalloc(ctx->max_ndp_size, GFP_KERNEL); + if (!ctx->delayed_ndp16) + goto error2; + dev_info(&intf->dev, "NDP will be placed at end of frame for this device."); + } + /* override ethtool_ops */ dev->net->ethtool_ops = &cdc_ncm_ethtool_ops; @@ -954,8 +967,11 @@ static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf) if (cdc_ncm_select_altsetting(intf) != CDC_NCM_COMM_ALTSETTING_NCM) return -ENODEV; - /* The NCM data altsetting is fixed */ - ret = cdc_ncm_bind_common(dev, intf, CDC_NCM_DATA_ALTSETTING_NCM); + /* The NCM data altsetting is fixed, so we hard-coded it. + * Additionally, generic NCM devices are assumed to accept arbitrarily + * placed NDP. + */ + ret = cdc_ncm_bind_common(dev, intf, CDC_NCM_DATA_ALTSETTING_NCM, 0); /* * We should get an event when network connection is "connected" or @@ -986,6 +1002,14 @@ static struct usb_cdc_ncm_ndp16 *cdc_ncm_ndp(struct cdc_ncm_ctx *ctx, struct sk_ struct usb_cdc_ncm_nth16 *nth16 = (void *)skb->data; size_t ndpoffset = le16_to_cpu(nth16->wNdpIndex); + /* If NDP should be moved to the end of the NCM package, we can't follow the + * NTH16 header as we would normally do. NDP isn't written to the SKB yet, and + * the wNdpIndex field in the header is actually not consistent with reality. It will be later. + */ + if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) + if (ctx->delayed_ndp16->dwSignature == sign) + return ctx->delayed_ndp16; + /* follow the chain of NDPs, looking for a match */ while (ndpoffset) { ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb->data + ndpoffset); @@ -995,7 +1019,8 @@ static struct usb_cdc_ncm_ndp16 *cdc_ncm_ndp(struct cdc_ncm_ctx *ctx, struct sk_ } /* align new NDP */ - cdc_ncm_align_tail(skb, ctx->tx_ndp_modulus, 0, ctx->tx_max); + if (!(ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END)) + cdc_ncm_align_tail(skb, ctx->tx_ndp_modulus, 0, ctx->tx_max); /* verify that there is room for the NDP and the datagram (reserve) */ if ((ctx->tx_max - skb->len - reserve) < ctx->max_ndp_size) @@ -1008,7 +1033,11 @@ static struct usb_cdc_ncm_ndp16 *cdc_ncm_ndp(struct cdc_ncm_ctx *ctx, struct sk_ nth16->wNdpIndex = cpu_to_le16(skb->len); /* push a new empty NDP */ - ndp16 = (struct usb_cdc_ncm_ndp16 *)memset(skb_put(skb, ctx->max_ndp_size), 0, ctx->max_ndp_size); + if (!(ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END)) + ndp16 = (struct usb_cdc_ncm_ndp16 *)memset(skb_put(skb, ctx->max_ndp_size), 0, ctx->max_ndp_size); + else + ndp16 = ctx->delayed_ndp16; + ndp16->dwSignature = sign; ndp16->wLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_ndp16) + sizeof(struct usb_cdc_ncm_dpe16)); return ndp16; @@ -1023,6 +1052,15 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) struct sk_buff *skb_out; u16 n = 0, index, ndplen; u8 ready2send = 0; + u32 delayed_ndp_size; + + /* When our NDP gets written in cdc_ncm_ndp(), then skb_out->len gets updated + * accordingly. Otherwise, we should check here. + */ + if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) + delayed_ndp_size = ctx->max_ndp_size; + else + delayed_ndp_size = 0; /* if there is a remaining skb, it gets priority */ if (skb != NULL) { @@ -1077,7 +1115,7 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) cdc_ncm_align_tail(skb_out, ctx->tx_modulus, ctx->tx_remainder, ctx->tx_max); /* check if we had enough room left for both NDP and frame */ - if (!ndp16 || skb_out->len + skb->len > ctx->tx_max) { + if (!ndp16 || skb_out->len + skb->len + delayed_ndp_size > ctx->tx_max) { if (n == 0) { /* won't fit, MTU problem? */ dev_kfree_skb_any(skb); @@ -1150,6 +1188,17 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) /* variables will be reset at next call */ } + /* If requested, put NDP at end of frame. */ + if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) { + nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data; + cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, ctx->tx_max); + nth16->wNdpIndex = cpu_to_le16(skb_out->len); + memcpy(skb_put(skb_out, ctx->max_ndp_size), ctx->delayed_ndp16, ctx->max_ndp_size); + + /* Zero out delayed NDP - signature checking will naturally fail. */ + ndp16 = memset(ctx->delayed_ndp16, 0, ctx->max_ndp_size); + } + /* If collected data size is less or equal ctx->min_tx_pkt * bytes, we send buffers as it is. If we get more data, it * would be more efficient for USB HS mobile device with DMA diff --git a/drivers/net/usb/huawei_cdc_ncm.c b/drivers/net/usb/huawei_cdc_ncm.c index 735f7dadb9a0..2680a65cd5e4 100644 --- a/drivers/net/usb/huawei_cdc_ncm.c +++ b/drivers/net/usb/huawei_cdc_ncm.c @@ -73,11 +73,14 @@ static int huawei_cdc_ncm_bind(struct usbnet *usbnet_dev, struct usb_driver *subdriver = ERR_PTR(-ENODEV); int ret = -ENODEV; struct huawei_cdc_ncm_state *drvstate = (void *)&usbnet_dev->data; + int drvflags = 0; /* altsetting should always be 1 for NCM devices - so we hard-coded - * it here + * it here. Some huawei devices will need the NDP part of the NCM package to + * be at the end of the frame. */ - ret = cdc_ncm_bind_common(usbnet_dev, intf, 1); + drvflags |= CDC_NCM_FLAG_NDP_TO_END; + ret = cdc_ncm_bind_common(usbnet_dev, intf, 1, drvflags); if (ret) goto err; diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index f603f362504b..9d43460ce3c7 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -757,6 +757,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */ {QMI_FIXED_INTF(0x1199, 0x901f, 8)}, /* Sierra Wireless EM7355 */ {QMI_FIXED_INTF(0x1199, 0x9041, 8)}, /* Sierra Wireless MC7305/MC7355 */ + {QMI_FIXED_INTF(0x1199, 0x9041, 10)}, /* Sierra Wireless MC7305/MC7355 */ {QMI_FIXED_INTF(0x1199, 0x9051, 8)}, /* Netgear AirCard 340U */ {QMI_FIXED_INTF(0x1199, 0x9053, 8)}, /* Sierra Wireless Modem */ {QMI_FIXED_INTF(0x1199, 0x9054, 8)}, /* Sierra Wireless Modem */ diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index aafa1a1898e4..ad8cbc6c9ee7 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -27,7 +27,7 @@ #include <linux/usb/cdc.h> /* Version Information */ -#define DRIVER_VERSION "v1.08.0 (2015/01/13)" +#define DRIVER_VERSION "v1.08.1 (2015/07/28)" #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>" #define DRIVER_DESC "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters" #define MODULENAME "r8152" @@ -494,6 +494,7 @@ enum rtl8152_flags { #define VENDOR_ID_REALTEK 0x0bda #define VENDOR_ID_SAMSUNG 0x04e8 #define VENDOR_ID_LENOVO 0x17ef +#define VENDOR_ID_NVIDIA 0x0955 #define MCU_TYPE_PLA 0x0100 #define MCU_TYPE_USB 0x0000 @@ -1901,11 +1902,10 @@ static void rtl_drop_queued_tx(struct r8152 *tp) static void rtl8152_tx_timeout(struct net_device *netdev) { struct r8152 *tp = netdev_priv(netdev); - int i; netif_warn(tp, tx_err, netdev, "Tx timeout\n"); - for (i = 0; i < RTL8152_MAX_TX; i++) - usb_unlink_urb(tp->tx_info[i].urb); + + usb_queue_reset_device(tp->intf); } static void rtl8152_set_rx_mode(struct net_device *netdev) @@ -2074,7 +2074,6 @@ static int rtl_start_rx(struct r8152 *tp) { int i, ret = 0; - napi_disable(&tp->napi); INIT_LIST_HEAD(&tp->rx_done); for (i = 0; i < RTL8152_MAX_RX; i++) { INIT_LIST_HEAD(&tp->rx_info[i].list); @@ -2082,7 +2081,6 @@ static int rtl_start_rx(struct r8152 *tp) if (ret) break; } - napi_enable(&tp->napi); if (ret && ++i < RTL8152_MAX_RX) { struct list_head rx_queue; @@ -2165,6 +2163,7 @@ static int rtl8153_enable(struct r8152 *tp) if (test_bit(RTL8152_UNPLUG, &tp->flags)) return -ENODEV; + usb_disable_lpm(tp->udev); set_tx_qlen(tp); rtl_set_eee_plus(tp); r8153_set_rx_early_timeout(tp); @@ -2336,11 +2335,61 @@ static void __rtl_set_wol(struct r8152 *tp, u32 wolopts) device_set_wakeup_enable(&tp->udev->dev, false); } +static void r8153_u1u2en(struct r8152 *tp, bool enable) +{ + u8 u1u2[8]; + + if (enable) + memset(u1u2, 0xff, sizeof(u1u2)); + else + memset(u1u2, 0x00, sizeof(u1u2)); + + usb_ocp_write(tp, USB_TOLERANCE, BYTE_EN_SIX_BYTES, sizeof(u1u2), u1u2); +} + +static void r8153_u2p3en(struct r8152 *tp, bool enable) +{ + u32 ocp_data; + + ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL); + if (enable && tp->version != RTL_VER_03 && tp->version != RTL_VER_04) + ocp_data |= U2P3_ENABLE; + else + ocp_data &= ~U2P3_ENABLE; + ocp_write_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL, ocp_data); +} + +static void r8153_power_cut_en(struct r8152 *tp, bool enable) +{ + u32 ocp_data; + + ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_POWER_CUT); + if (enable) + ocp_data |= PWR_EN | PHASE2_EN; + else + ocp_data &= ~(PWR_EN | PHASE2_EN); + ocp_write_word(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); + + ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0); + ocp_data &= ~PCUT_STATUS; + ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data); +} + +static bool rtl_can_wakeup(struct r8152 *tp) +{ + struct usb_device *udev = tp->udev; + + return (udev->actconfig->desc.bmAttributes & USB_CONFIG_ATT_WAKEUP); +} + static void rtl_runtime_suspend_enable(struct r8152 *tp, bool enable) { if (enable) { u32 ocp_data; + r8153_u1u2en(tp, false); + r8153_u2p3en(tp, false); + __rtl_set_wol(tp, WAKE_ANY); ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG); @@ -2352,6 +2401,8 @@ static void rtl_runtime_suspend_enable(struct r8152 *tp, bool enable) ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML); } else { __rtl_set_wol(tp, tp->saved_wolopts); + r8153_u2p3en(tp, true); + r8153_u1u2en(tp, true); } } @@ -2598,46 +2649,6 @@ static void r8153_hw_phy_cfg(struct r8152 *tp) set_bit(PHY_RESET, &tp->flags); } -static void r8153_u1u2en(struct r8152 *tp, bool enable) -{ - u8 u1u2[8]; - - if (enable) - memset(u1u2, 0xff, sizeof(u1u2)); - else - memset(u1u2, 0x00, sizeof(u1u2)); - - usb_ocp_write(tp, USB_TOLERANCE, BYTE_EN_SIX_BYTES, sizeof(u1u2), u1u2); -} - -static void r8153_u2p3en(struct r8152 *tp, bool enable) -{ - u32 ocp_data; - - ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL); - if (enable) - ocp_data |= U2P3_ENABLE; - else - ocp_data &= ~U2P3_ENABLE; - ocp_write_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL, ocp_data); -} - -static void r8153_power_cut_en(struct r8152 *tp, bool enable) -{ - u32 ocp_data; - - ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_POWER_CUT); - if (enable) - ocp_data |= PWR_EN | PHASE2_EN; - else - ocp_data &= ~(PWR_EN | PHASE2_EN); - ocp_write_word(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); - - ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0); - ocp_data &= ~PCUT_STATUS; - ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data); -} - static void r8153_first_init(struct r8152 *tp) { u32 ocp_data; @@ -2780,6 +2791,7 @@ static void rtl8153_disable(struct r8152 *tp) r8153_disable_aldps(tp); rtl_disable(tp); r8153_enable_aldps(tp); + usb_enable_lpm(tp->udev); } static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex) @@ -2900,9 +2912,13 @@ static void rtl8153_up(struct r8152 *tp) if (test_bit(RTL8152_UNPLUG, &tp->flags)) return; + r8153_u1u2en(tp, false); r8153_disable_aldps(tp); r8153_first_init(tp); r8153_enable_aldps(tp); + r8153_u2p3en(tp, true); + r8153_u1u2en(tp, true); + usb_enable_lpm(tp->udev); } static void rtl8153_down(struct r8152 *tp) @@ -2913,6 +2929,7 @@ static void rtl8153_down(struct r8152 *tp) } r8153_u1u2en(tp, false); + r8153_u2p3en(tp, false); r8153_power_cut_en(tp, false); r8153_disable_aldps(tp); r8153_enter_oob(tp); @@ -2931,8 +2948,10 @@ static void set_carrier(struct r8152 *tp) if (!netif_carrier_ok(netdev)) { tp->rtl_ops.enable(tp); set_bit(RTL8152_SET_RX_MODE, &tp->flags); + napi_disable(&tp->napi); netif_carrier_on(netdev); rtl_start_rx(tp); + napi_enable(&tp->napi); } } else { if (netif_carrier_ok(netdev)) { @@ -3251,6 +3270,7 @@ static void r8153_init(struct r8152 *tp) msleep(20); } + usb_disable_lpm(tp->udev); r8153_u2p3en(tp, false); if (tp->version == RTL_VER_04) { @@ -3318,6 +3338,59 @@ static void r8153_init(struct r8152 *tp) r8153_enable_aldps(tp); r8152b_enable_fc(tp); rtl_tally_reset(tp); + r8153_u2p3en(tp, true); +} + +static int rtl8152_pre_reset(struct usb_interface *intf) +{ + struct r8152 *tp = usb_get_intfdata(intf); + struct net_device *netdev; + + if (!tp) + return 0; + + netdev = tp->netdev; + if (!netif_running(netdev)) + return 0; + + napi_disable(&tp->napi); + clear_bit(WORK_ENABLE, &tp->flags); + usb_kill_urb(tp->intr_urb); + cancel_delayed_work_sync(&tp->schedule); + if (netif_carrier_ok(netdev)) { + netif_stop_queue(netdev); + mutex_lock(&tp->control); + tp->rtl_ops.disable(tp); + mutex_unlock(&tp->control); + } + + return 0; +} + +static int rtl8152_post_reset(struct usb_interface *intf) +{ + struct r8152 *tp = usb_get_intfdata(intf); + struct net_device *netdev; + + if (!tp) + return 0; + + netdev = tp->netdev; + if (!netif_running(netdev)) + return 0; + + set_bit(WORK_ENABLE, &tp->flags); + if (netif_carrier_ok(netdev)) { + mutex_lock(&tp->control); + tp->rtl_ops.enable(tp); + rtl8152_set_rx_mode(netdev); + mutex_unlock(&tp->control); + netif_wake_queue(netdev); + } + + napi_enable(&tp->napi); + + return 0; } static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message) @@ -3373,9 +3446,11 @@ static int rtl8152_resume(struct usb_interface *intf) if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) { rtl_runtime_suspend_enable(tp, false); clear_bit(SELECTIVE_SUSPEND, &tp->flags); + napi_disable(&tp->napi); set_bit(WORK_ENABLE, &tp->flags); if (netif_carrier_ok(tp->netdev)) rtl_start_rx(tp); + napi_enable(&tp->napi); } else { tp->rtl_ops.up(tp); rtl8152_set_speed(tp, AUTONEG_ENABLE, @@ -3402,12 +3477,15 @@ static void rtl8152_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) if (usb_autopm_get_interface(tp->intf) < 0) return; - mutex_lock(&tp->control); - - wol->supported = WAKE_ANY; - wol->wolopts = __rtl_get_wol(tp); - - mutex_unlock(&tp->control); + if (!rtl_can_wakeup(tp)) { + wol->supported = 0; + wol->wolopts = 0; + } else { + mutex_lock(&tp->control); + wol->supported = WAKE_ANY; + wol->wolopts = __rtl_get_wol(tp); + mutex_unlock(&tp->control); + } usb_autopm_put_interface(tp->intf); } @@ -3417,6 +3495,9 @@ static int rtl8152_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) struct r8152 *tp = netdev_priv(dev); int ret; + if (!rtl_can_wakeup(tp)) + return -EOPNOTSUPP; + ret = usb_autopm_get_interface(tp->intf); if (ret < 0) goto out_set_wol; @@ -4058,6 +4139,9 @@ static int rtl8152_probe(struct usb_interface *intf, goto out1; } + if (!rtl_can_wakeup(tp)) + __rtl_set_wol(tp, 0); + tp->saved_wolopts = __rtl_get_wol(tp); if (tp->saved_wolopts) device_set_wakeup_enable(&udev->dev, true); @@ -4117,6 +4201,7 @@ static struct usb_device_id rtl8152_table[] = { {REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x304f)}, + {REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff)}, {} }; @@ -4130,6 +4215,8 @@ static struct usb_driver rtl8152_driver = { .suspend = rtl8152_suspend, .resume = rtl8152_resume, .reset_resume = rtl8152_resume, + .pre_reset = rtl8152_pre_reset, + .post_reset = rtl8152_post_reset, .supports_autosuspend = 1, .disable_hub_initiated_lpm = 1, }; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 63c7810e1545..7fbca37a1adf 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1828,7 +1828,8 @@ static int virtnet_probe(struct virtio_device *vdev) else vi->hdr_len = sizeof(struct virtio_net_hdr); - if (virtio_has_feature(vdev, VIRTIO_F_ANY_LAYOUT)) + if (virtio_has_feature(vdev, VIRTIO_F_ANY_LAYOUT) || + virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) vi->any_header_sg = true; if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index da11bb5e9c7f..46f4caddccbe 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -1216,7 +1216,7 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq, static const u32 rxprod_reg[2] = { VMXNET3_REG_RXPROD, VMXNET3_REG_RXPROD2 }; - u32 num_rxd = 0; + u32 num_pkts = 0; bool skip_page_frags = false; struct Vmxnet3_RxCompDesc *rcd; struct vmxnet3_rx_ctx *ctx = &rq->rx_ctx; @@ -1235,13 +1235,12 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq, struct Vmxnet3_RxDesc *rxd; u32 idx, ring_idx; struct vmxnet3_cmd_ring *ring = NULL; - if (num_rxd >= quota) { + if (num_pkts >= quota) { /* we may stop even before we see the EOP desc of * the current pkt */ break; } - num_rxd++; BUG_ON(rcd->rqID != rq->qid && rcd->rqID != rq->qid2); idx = rcd->rxdIdx; ring_idx = rcd->rqID < adapter->num_rx_queues ? 0 : 1; @@ -1413,6 +1412,7 @@ not_lro: napi_gro_receive(&rq->napi, skb); ctx->skb = NULL; + num_pkts++; } rcd_done: @@ -1443,7 +1443,7 @@ rcd_done: &rq->comp_ring.base[rq->comp_ring.next2proc].rcd, &rxComp); } - return num_rxd; + return num_pkts; } diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c index feacc3b994b7..2f0bd6955f33 100644 --- a/drivers/net/wan/z85230.c +++ b/drivers/net/wan/z85230.c @@ -1044,7 +1044,7 @@ EXPORT_SYMBOL(z8530_sync_dma_close); * @dev: The network device to attach * @c: The Z8530 channel to configure in sync DMA mode. * - * Set up a Z85x30 device for synchronous DMA tranmission. One + * Set up a Z85x30 device for synchronous DMA transmission. One * ISA DMA channel must be available for this to work. The receive * side is run in PIO mode, but then it has the bigger FIFO. */ diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 5e15e8e10ed3..a31a6804dc34 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -279,6 +279,7 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah) return; case AR9300_DEVID_QCA956X: ah->hw_version.macVersion = AR_SREV_VERSION_9561; + return; } val = REG_READ(ah, AR_SREV) & AR_SREV_ID; diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index d56064861a9c..d45dc021cda2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -438,6 +438,12 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl) #define RX_QUEUE_MASK 255 #define RX_QUEUE_SIZE_LOG 8 +/* + * RX related structures and functions + */ +#define RX_FREE_BUFFERS 64 +#define RX_LOW_WATERMARK 8 + /** * struct iwl_rb_status - reserve buffer status * host memory mapped FH registers diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index 80fefe7d7b8c..3b8e85e51002 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c @@ -540,13 +540,11 @@ static void iwl_set_hw_address_family_8000(struct device *dev, hw_addr = (const u8 *)(mac_override + MAC_ADDRESS_OVERRIDE_FAMILY_8000); - /* The byte order is little endian 16 bit, meaning 214365 */ - data->hw_addr[0] = hw_addr[1]; - data->hw_addr[1] = hw_addr[0]; - data->hw_addr[2] = hw_addr[3]; - data->hw_addr[3] = hw_addr[2]; - data->hw_addr[4] = hw_addr[5]; - data->hw_addr[5] = hw_addr[4]; + /* + * Store the MAC address from MAO section. + * No byte swapping is required in MAO section + */ + memcpy(data->hw_addr, hw_addr, ETH_ALEN); /* * Force the use of the OTP MAC address in case of reserved MAC diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h index 5e4cbdb44c60..737774a01c74 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h @@ -660,7 +660,8 @@ struct iwl_scan_config { * iwl_umac_scan_flags *@IWL_UMAC_SCAN_FLAG_PREEMPTIVE: scan process triggered by this scan request * can be preempted by other scan requests with higher priority. - * The low priority scan is aborted. + * The low priority scan will be resumed when the higher proirity scan is + * completed. *@IWL_UMAC_SCAN_FLAG_START_NOTIF: notification will be sent to the driver * when scan starts. */ diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 5de144968723..5000bfcded61 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -1109,6 +1109,9 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, cmd->uid = cpu_to_le32(uid); cmd->general_flags = cpu_to_le32(iwl_mvm_scan_umac_flags(mvm, params)); + if (type == IWL_MVM_SCAN_SCHED) + cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE); + if (iwl_mvm_scan_use_ebs(mvm, vif, n_iterations)) cmd->channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index d68dc697a4a0..26f076e82149 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -1401,6 +1401,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE); u8 sta_id; int ret; + static const u8 __maybe_unused zero_addr[ETH_ALEN] = {0}; lockdep_assert_held(&mvm->mutex); @@ -1467,7 +1468,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, end: IWL_DEBUG_WEP(mvm, "key: cipher=%x len=%d idx=%d sta=%pM ret=%d\n", keyconf->cipher, keyconf->keylen, keyconf->keyidx, - sta->addr, ret); + sta ? sta->addr : zero_addr, ret); return ret; } diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index d24b6a83e68c..e472729e5f14 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c @@ -86,7 +86,7 @@ void iwl_mvm_te_clear_data(struct iwl_mvm *mvm, { lockdep_assert_held(&mvm->time_event_lock); - if (te_data->id == TE_MAX) + if (!te_data->vif) return; list_del(&te_data->list); diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 7ba7a118ff5c..89116864d2a0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c @@ -252,7 +252,7 @@ void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd, if (info->band == IEEE80211_BAND_2GHZ && !iwl_mvm_bt_coex_is_shared_ant_avail(mvm)) - rate_flags = BIT(mvm->cfg->non_shared_ant) << RATE_MCS_ANT_POS; + rate_flags = mvm->cfg->non_shared_ant << RATE_MCS_ANT_POS; else rate_flags = BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS; diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 2ed1e4d2774d..9f65c1cff1b1 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c @@ -368,12 +368,14 @@ static const struct pci_device_id iwl_hw_card_ids[] = { /* 3165 Series */ {IWL_PCI_DEVICE(0x3165, 0x4010, iwl3165_2ac_cfg)}, {IWL_PCI_DEVICE(0x3165, 0x4012, iwl3165_2ac_cfg)}, + {IWL_PCI_DEVICE(0x3166, 0x4212, iwl3165_2ac_cfg)}, {IWL_PCI_DEVICE(0x3165, 0x4410, iwl3165_2ac_cfg)}, {IWL_PCI_DEVICE(0x3165, 0x4510, iwl3165_2ac_cfg)}, {IWL_PCI_DEVICE(0x3165, 0x4110, iwl3165_2ac_cfg)}, {IWL_PCI_DEVICE(0x3166, 0x4310, iwl3165_2ac_cfg)}, {IWL_PCI_DEVICE(0x3166, 0x4210, iwl3165_2ac_cfg)}, {IWL_PCI_DEVICE(0x3165, 0x8010, iwl3165_2ac_cfg)}, + {IWL_PCI_DEVICE(0x3165, 0x8110, iwl3165_2ac_cfg)}, /* 7265 Series */ {IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)}, @@ -426,9 +428,8 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x24F4, 0x1130, iwl8260_2ac_cfg)}, {IWL_PCI_DEVICE(0x24F4, 0x1030, iwl8260_2ac_cfg)}, {IWL_PCI_DEVICE(0x24F3, 0xC010, iwl8260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x24F3, 0xC110, iwl8260_2ac_cfg)}, {IWL_PCI_DEVICE(0x24F3, 0xD010, iwl8260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x24F4, 0xC030, iwl8260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x24F4, 0xD030, iwl8260_2ac_cfg)}, {IWL_PCI_DEVICE(0x24F3, 0xC050, iwl8260_2ac_cfg)}, {IWL_PCI_DEVICE(0x24F3, 0xD050, iwl8260_2ac_cfg)}, {IWL_PCI_DEVICE(0x24F3, 0x8010, iwl8260_2ac_cfg)}, diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index 31f72a61cc3f..376b84e54ad7 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h @@ -44,15 +44,6 @@ #include "iwl-io.h" #include "iwl-op-mode.h" -/* - * RX related structures and functions - */ -#define RX_NUM_QUEUES 1 -#define RX_POST_REQ_ALLOC 2 -#define RX_CLAIM_REQ_ALLOC 8 -#define RX_POOL_SIZE ((RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC) * RX_NUM_QUEUES) -#define RX_LOW_WATERMARK 8 - struct iwl_host_cmd; /*This file includes the declaration that are internal to the @@ -86,29 +77,29 @@ struct isr_statistics { * struct iwl_rxq - Rx queue * @bd: driver's pointer to buffer of receive buffer descriptors (rbd) * @bd_dma: bus address of buffer of receive buffer descriptors (rbd) + * @pool: + * @queue: * @read: Shared index to newest available Rx buffer * @write: Shared index to oldest written Rx packet * @free_count: Number of pre-allocated buffers in rx_free - * @used_count: Number of RBDs handled to allocator to use for allocation * @write_actual: - * @rx_free: list of RBDs with allocated RB ready for use - * @rx_used: list of RBDs with no RB attached + * @rx_free: list of free SKBs for use + * @rx_used: List of Rx buffers with no SKB * @need_update: flag to indicate we need to update read/write index * @rb_stts: driver's pointer to receive buffer status * @rb_stts_dma: bus address of receive buffer status * @lock: - * @pool: initial pool of iwl_rx_mem_buffer for the queue - * @queue: actual rx queue * * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers */ struct iwl_rxq { __le32 *bd; dma_addr_t bd_dma; + struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; + struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; u32 read; u32 write; u32 free_count; - u32 used_count; u32 write_actual; struct list_head rx_free; struct list_head rx_used; @@ -116,32 +107,6 @@ struct iwl_rxq { struct iwl_rb_status *rb_stts; dma_addr_t rb_stts_dma; spinlock_t lock; - struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE]; - struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; -}; - -/** - * struct iwl_rb_allocator - Rx allocator - * @pool: initial pool of allocator - * @req_pending: number of requests the allcator had not processed yet - * @req_ready: number of requests honored and ready for claiming - * @rbd_allocated: RBDs with pages allocated and ready to be handled to - * the queue. This is a list of &struct iwl_rx_mem_buffer - * @rbd_empty: RBDs with no page attached for allocator use. This is a list - * of &struct iwl_rx_mem_buffer - * @lock: protects the rbd_allocated and rbd_empty lists - * @alloc_wq: work queue for background calls - * @rx_alloc: work struct for background calls - */ -struct iwl_rb_allocator { - struct iwl_rx_mem_buffer pool[RX_POOL_SIZE]; - atomic_t req_pending; - atomic_t req_ready; - struct list_head rbd_allocated; - struct list_head rbd_empty; - spinlock_t lock; - struct workqueue_struct *alloc_wq; - struct work_struct rx_alloc; }; struct iwl_dma_ptr { @@ -285,7 +250,7 @@ iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx) /** * struct iwl_trans_pcie - PCIe transport specific data * @rxq: all the RX queue data - * @rba: allocator for RX replenishing + * @rx_replenish: work that will be called when buffers need to be allocated * @drv - pointer to iwl_drv * @trans: pointer to the generic transport area * @scd_base_addr: scheduler sram base address in SRAM @@ -308,7 +273,7 @@ iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx) */ struct iwl_trans_pcie { struct iwl_rxq rxq; - struct iwl_rb_allocator rba; + struct work_struct rx_replenish; struct iwl_trans *trans; struct iwl_drv *drv; diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index a3fbaa0ef5e0..adad8d0fae7f 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -74,29 +74,16 @@ * resets the Rx queue buffers with new memory. * * The management in the driver is as follows: - * + A list of pre-allocated RBDs is stored in iwl->rxq->rx_free. - * When the interrupt handler is called, the request is processed. - * The page is either stolen - transferred to the upper layer - * or reused - added immediately to the iwl->rxq->rx_free list. - * + When the page is stolen - the driver updates the matching queue's used - * count, detaches the RBD and transfers it to the queue used list. - * When there are two used RBDs - they are transferred to the allocator empty - * list. Work is then scheduled for the allocator to start allocating - * eight buffers. - * When there are another 6 used RBDs - they are transferred to the allocator - * empty list and the driver tries to claim the pre-allocated buffers and - * add them to iwl->rxq->rx_free. If it fails - it continues to claim them - * until ready. - * When there are 8+ buffers in the free list - either from allocation or from - * 8 reused unstolen pages - restock is called to update the FW and indexes. - * + In order to make sure the allocator always has RBDs to use for allocation - * the allocator has initial pool in the size of num_queues*(8-2) - the - * maximum missing RBDs per allocation request (request posted with 2 - * empty RBDs, there is no guarantee when the other 6 RBDs are supplied). - * The queues supplies the recycle of the rest of the RBDs. + * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free. When + * iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled + * to replenish the iwl->rxq->rx_free. + * + In iwl_pcie_rx_replenish (scheduled) if 'processed' != 'read' then the + * iwl->rxq is replenished and the READ INDEX is updated (updating the + * 'processed' and 'read' driver indexes as well) * + A received packet is processed and handed to the kernel network stack, * detached from the iwl->rxq. The driver 'processed' index is updated. - * + If there are no allocated buffers in iwl->rxq->rx_free, + * + The Host/Firmware iwl->rxq is replenished at irq thread time from the + * rx_free list. If there are no allocated buffers in iwl->rxq->rx_free, * the READ INDEX is not incremented and iwl->status(RX_STALLED) is set. * If there were enough free buffers and RX_STALLED is set it is cleared. * @@ -105,32 +92,18 @@ * * iwl_rxq_alloc() Allocates rx_free * iwl_pcie_rx_replenish() Replenishes rx_free list from rx_used, and calls - * iwl_pcie_rxq_restock. - * Used only during initialization. + * iwl_pcie_rxq_restock * iwl_pcie_rxq_restock() Moves available buffers from rx_free into Rx * queue, updates firmware pointers, and updates - * the WRITE index. - * iwl_pcie_rx_allocator() Background work for allocating pages. + * the WRITE index. If insufficient rx_free buffers + * are available, schedules iwl_pcie_rx_replenish * * -- enable interrupts -- * ISR - iwl_rx() Detach iwl_rx_mem_buffers from pool up to the * READ INDEX, detaching the SKB from the pool. * Moves the packet buffer from queue to rx_used. - * Posts and claims requests to the allocator. * Calls iwl_pcie_rxq_restock to refill any empty * slots. - * - * RBD life-cycle: - * - * Init: - * rxq.pool -> rxq.rx_used -> rxq.rx_free -> rxq.queue - * - * Regular Receive interrupt: - * Page Stolen: - * rxq.queue -> rxq.rx_used -> allocator.rbd_empty -> - * allocator.rbd_allocated -> rxq.rx_free -> rxq.queue - * Page not Stolen: - * rxq.queue -> rxq.rx_free -> rxq.queue * ... * */ @@ -267,6 +240,10 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans) rxq->free_count--; } spin_unlock(&rxq->lock); + /* If the pre-allocated buffer pool is dropping low, schedule to + * refill it */ + if (rxq->free_count <= RX_LOW_WATERMARK) + schedule_work(&trans_pcie->rx_replenish); /* If we've added more space for the firmware to place data, tell it. * Increment device's write pointer in multiples of 8. */ @@ -278,44 +255,6 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans) } /* - * iwl_pcie_rx_alloc_page - allocates and returns a page. - * - */ -static struct page *iwl_pcie_rx_alloc_page(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; - struct page *page; - gfp_t gfp_mask = GFP_KERNEL; - - if (rxq->free_count > RX_LOW_WATERMARK) - gfp_mask |= __GFP_NOWARN; - - if (trans_pcie->rx_page_order > 0) - gfp_mask |= __GFP_COMP; - - /* Alloc a new receive buffer */ - page = alloc_pages(gfp_mask, trans_pcie->rx_page_order); - if (!page) { - if (net_ratelimit()) - IWL_DEBUG_INFO(trans, "alloc_pages failed, order: %d\n", - trans_pcie->rx_page_order); - /* Issue an error if the hardware has consumed more than half - * of its free buffer list and we don't have enough - * pre-allocated buffers. -` */ - if (rxq->free_count <= RX_LOW_WATERMARK && - iwl_rxq_space(rxq) > (RX_QUEUE_SIZE / 2) && - net_ratelimit()) - IWL_CRIT(trans, - "Failed to alloc_pages with GFP_KERNEL. Only %u free buffers remaining.\n", - rxq->free_count); - return NULL; - } - return page; -} - -/* * iwl_pcie_rxq_alloc_rbs - allocate a page for each used RBD * * A used RBD is an Rx buffer that has been given to the stack. To use it again @@ -324,12 +263,13 @@ static struct page *iwl_pcie_rx_alloc_page(struct iwl_trans *trans) * iwl_pcie_rxq_restock. The latter function will update the HW to use the newly * allocated buffers. */ -static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans) +static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rxq *rxq = &trans_pcie->rxq; struct iwl_rx_mem_buffer *rxb; struct page *page; + gfp_t gfp_mask = priority; while (1) { spin_lock(&rxq->lock); @@ -339,10 +279,32 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans) } spin_unlock(&rxq->lock); + if (rxq->free_count > RX_LOW_WATERMARK) + gfp_mask |= __GFP_NOWARN; + + if (trans_pcie->rx_page_order > 0) + gfp_mask |= __GFP_COMP; + /* Alloc a new receive buffer */ - page = iwl_pcie_rx_alloc_page(trans); - if (!page) + page = alloc_pages(gfp_mask, trans_pcie->rx_page_order); + if (!page) { + if (net_ratelimit()) + IWL_DEBUG_INFO(trans, "alloc_pages failed, " + "order: %d\n", + trans_pcie->rx_page_order); + + if ((rxq->free_count <= RX_LOW_WATERMARK) && + net_ratelimit()) + IWL_CRIT(trans, "Failed to alloc_pages with %s." + "Only %u free buffers remaining.\n", + priority == GFP_ATOMIC ? + "GFP_ATOMIC" : "GFP_KERNEL", + rxq->free_count); + /* We don't reschedule replenish work here -- we will + * call the restock method and if it still needs + * more buffers it will schedule replenish */ return; + } spin_lock(&rxq->lock); @@ -393,7 +355,7 @@ static void iwl_pcie_rxq_free_rbs(struct iwl_trans *trans) lockdep_assert_held(&rxq->lock); - for (i = 0; i < RX_QUEUE_SIZE; i++) { + for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { if (!rxq->pool[i].page) continue; dma_unmap_page(trans->dev, rxq->pool[i].page_dma, @@ -410,144 +372,32 @@ static void iwl_pcie_rxq_free_rbs(struct iwl_trans *trans) * When moving to rx_free an page is allocated for the slot. * * Also restock the Rx queue via iwl_pcie_rxq_restock. - * This is called only during initialization + * This is called as a scheduled work item (except for during initialization) */ -static void iwl_pcie_rx_replenish(struct iwl_trans *trans) +static void iwl_pcie_rx_replenish(struct iwl_trans *trans, gfp_t gfp) { - iwl_pcie_rxq_alloc_rbs(trans); + iwl_pcie_rxq_alloc_rbs(trans, gfp); iwl_pcie_rxq_restock(trans); } -/* - * iwl_pcie_rx_allocator - Allocates pages in the background for RX queues - * - * Allocates for each received request 8 pages - * Called as a scheduled work item. - */ -static void iwl_pcie_rx_allocator(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rb_allocator *rba = &trans_pcie->rba; - - while (atomic_read(&rba->req_pending)) { - int i; - struct list_head local_empty; - struct list_head local_allocated; - - INIT_LIST_HEAD(&local_allocated); - spin_lock(&rba->lock); - /* swap out the entire rba->rbd_empty to a local list */ - list_replace_init(&rba->rbd_empty, &local_empty); - spin_unlock(&rba->lock); - - for (i = 0; i < RX_CLAIM_REQ_ALLOC;) { - struct iwl_rx_mem_buffer *rxb; - struct page *page; - - /* List should never be empty - each reused RBD is - * returned to the list, and initial pool covers any - * possible gap between the time the page is allocated - * to the time the RBD is added. - */ - BUG_ON(list_empty(&local_empty)); - /* Get the first rxb from the rbd list */ - rxb = list_first_entry(&local_empty, - struct iwl_rx_mem_buffer, list); - BUG_ON(rxb->page); - - /* Alloc a new receive buffer */ - page = iwl_pcie_rx_alloc_page(trans); - if (!page) - continue; - rxb->page = page; - - /* Get physical address of the RB */ - rxb->page_dma = dma_map_page(trans->dev, page, 0, - PAGE_SIZE << trans_pcie->rx_page_order, - DMA_FROM_DEVICE); - if (dma_mapping_error(trans->dev, rxb->page_dma)) { - rxb->page = NULL; - __free_pages(page, trans_pcie->rx_page_order); - continue; - } - /* dma address must be no more than 36 bits */ - BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); - /* and also 256 byte aligned! */ - BUG_ON(rxb->page_dma & DMA_BIT_MASK(8)); - - /* move the allocated entry to the out list */ - list_move(&rxb->list, &local_allocated); - i++; - } - - spin_lock(&rba->lock); - /* add the allocated rbds to the allocator allocated list */ - list_splice_tail(&local_allocated, &rba->rbd_allocated); - /* add the unused rbds back to the allocator empty list */ - list_splice_tail(&local_empty, &rba->rbd_empty); - spin_unlock(&rba->lock); - - atomic_dec(&rba->req_pending); - atomic_inc(&rba->req_ready); - } -} - -/* - * iwl_pcie_rx_allocator_get - Returns the pre-allocated pages -.* -.* Called by queue when the queue posted allocation request and - * has freed 8 RBDs in order to restock itself. - */ -static int iwl_pcie_rx_allocator_get(struct iwl_trans *trans, - struct iwl_rx_mem_buffer - *out[RX_CLAIM_REQ_ALLOC]) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rb_allocator *rba = &trans_pcie->rba; - int i; - - if (atomic_dec_return(&rba->req_ready) < 0) { - atomic_inc(&rba->req_ready); - IWL_DEBUG_RX(trans, - "Allocation request not ready, pending requests = %d\n", - atomic_read(&rba->req_pending)); - return -ENOMEM; - } - - spin_lock(&rba->lock); - for (i = 0; i < RX_CLAIM_REQ_ALLOC; i++) { - /* Get next free Rx buffer, remove it from free list */ - out[i] = list_first_entry(&rba->rbd_allocated, - struct iwl_rx_mem_buffer, list); - list_del(&out[i]->list); - } - spin_unlock(&rba->lock); - - return 0; -} - -static void iwl_pcie_rx_allocator_work(struct work_struct *data) +static void iwl_pcie_rx_replenish_work(struct work_struct *data) { - struct iwl_rb_allocator *rba_p = - container_of(data, struct iwl_rb_allocator, rx_alloc); struct iwl_trans_pcie *trans_pcie = - container_of(rba_p, struct iwl_trans_pcie, rba); + container_of(data, struct iwl_trans_pcie, rx_replenish); - iwl_pcie_rx_allocator(trans_pcie->trans); + iwl_pcie_rx_replenish(trans_pcie->trans, GFP_KERNEL); } static int iwl_pcie_rx_alloc(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rxq *rxq = &trans_pcie->rxq; - struct iwl_rb_allocator *rba = &trans_pcie->rba; struct device *dev = trans->dev; memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq)); spin_lock_init(&rxq->lock); - spin_lock_init(&rba->lock); if (WARN_ON(rxq->bd || rxq->rb_stts)) return -EINVAL; @@ -637,49 +487,15 @@ static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq) INIT_LIST_HEAD(&rxq->rx_free); INIT_LIST_HEAD(&rxq->rx_used); rxq->free_count = 0; - rxq->used_count = 0; - for (i = 0; i < RX_QUEUE_SIZE; i++) + for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) list_add(&rxq->pool[i].list, &rxq->rx_used); } -static void iwl_pcie_rx_init_rba(struct iwl_rb_allocator *rba) -{ - int i; - - lockdep_assert_held(&rba->lock); - - INIT_LIST_HEAD(&rba->rbd_allocated); - INIT_LIST_HEAD(&rba->rbd_empty); - - for (i = 0; i < RX_POOL_SIZE; i++) - list_add(&rba->pool[i].list, &rba->rbd_empty); -} - -static void iwl_pcie_rx_free_rba(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rb_allocator *rba = &trans_pcie->rba; - int i; - - lockdep_assert_held(&rba->lock); - - for (i = 0; i < RX_POOL_SIZE; i++) { - if (!rba->pool[i].page) - continue; - dma_unmap_page(trans->dev, rba->pool[i].page_dma, - PAGE_SIZE << trans_pcie->rx_page_order, - DMA_FROM_DEVICE); - __free_pages(rba->pool[i].page, trans_pcie->rx_page_order); - rba->pool[i].page = NULL; - } -} - int iwl_pcie_rx_init(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rxq *rxq = &trans_pcie->rxq; - struct iwl_rb_allocator *rba = &trans_pcie->rba; int i, err; if (!rxq->bd) { @@ -687,21 +503,11 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) if (err) return err; } - if (!rba->alloc_wq) - rba->alloc_wq = alloc_workqueue("rb_allocator", - WQ_HIGHPRI | WQ_UNBOUND, 1); - INIT_WORK(&rba->rx_alloc, iwl_pcie_rx_allocator_work); - - spin_lock(&rba->lock); - atomic_set(&rba->req_pending, 0); - atomic_set(&rba->req_ready, 0); - /* free all first - we might be reconfigured for a different size */ - iwl_pcie_rx_free_rba(trans); - iwl_pcie_rx_init_rba(rba); - spin_unlock(&rba->lock); spin_lock(&rxq->lock); + INIT_WORK(&trans_pcie->rx_replenish, iwl_pcie_rx_replenish_work); + /* free all first - we might be reconfigured for a different size */ iwl_pcie_rxq_free_rbs(trans); iwl_pcie_rx_init_rxb_lists(rxq); @@ -716,7 +522,7 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts)); spin_unlock(&rxq->lock); - iwl_pcie_rx_replenish(trans); + iwl_pcie_rx_replenish(trans, GFP_KERNEL); iwl_pcie_rx_hw_init(trans, rxq); @@ -731,7 +537,6 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rxq *rxq = &trans_pcie->rxq; - struct iwl_rb_allocator *rba = &trans_pcie->rba; /*if rxq->bd is NULL, it means that nothing has been allocated, * exit now */ @@ -740,15 +545,7 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) return; } - cancel_work_sync(&rba->rx_alloc); - if (rba->alloc_wq) { - destroy_workqueue(rba->alloc_wq); - rba->alloc_wq = NULL; - } - - spin_lock(&rba->lock); - iwl_pcie_rx_free_rba(trans); - spin_unlock(&rba->lock); + cancel_work_sync(&trans_pcie->rx_replenish); spin_lock(&rxq->lock); iwl_pcie_rxq_free_rbs(trans); @@ -769,43 +566,6 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) rxq->rb_stts = NULL; } -/* - * iwl_pcie_rx_reuse_rbd - Recycle used RBDs - * - * Called when a RBD can be reused. The RBD is transferred to the allocator. - * When there are 2 empty RBDs - a request for allocation is posted - */ -static void iwl_pcie_rx_reuse_rbd(struct iwl_trans *trans, - struct iwl_rx_mem_buffer *rxb, - struct iwl_rxq *rxq) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rb_allocator *rba = &trans_pcie->rba; - - /* Count the used RBDs */ - rxq->used_count++; - - /* Move the RBD to the used list, will be moved to allocator in batches - * before claiming or posting a request*/ - list_add_tail(&rxb->list, &rxq->rx_used); - - /* If we have RX_POST_REQ_ALLOC new released rx buffers - - * issue a request for allocator. Modulo RX_CLAIM_REQ_ALLOC is - * used for the case we failed to claim RX_CLAIM_REQ_ALLOC, - * after but we still need to post another request. - */ - if ((rxq->used_count % RX_CLAIM_REQ_ALLOC) == RX_POST_REQ_ALLOC) { - /* Move the 2 RBDs to the allocator ownership. - Allocator has another 6 from pool for the request completion*/ - spin_lock(&rba->lock); - list_splice_tail_init(&rxq->rx_used, &rba->rbd_empty); - spin_unlock(&rba->lock); - - atomic_inc(&rba->req_pending); - queue_work(rba->alloc_wq, &rba->rx_alloc); - } -} - static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb) { @@ -928,13 +688,13 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, */ __free_pages(rxb->page, trans_pcie->rx_page_order); rxb->page = NULL; - iwl_pcie_rx_reuse_rbd(trans, rxb, rxq); + list_add_tail(&rxb->list, &rxq->rx_used); } else { list_add_tail(&rxb->list, &rxq->rx_free); rxq->free_count++; } } else - iwl_pcie_rx_reuse_rbd(trans, rxb, rxq); + list_add_tail(&rxb->list, &rxq->rx_used); } /* @@ -944,7 +704,10 @@ static void iwl_pcie_rx_handle(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rxq *rxq = &trans_pcie->rxq; - u32 r, i, j; + u32 r, i; + u8 fill_rx = 0; + u32 count = 8; + int total_empty; restart: spin_lock(&rxq->lock); @@ -957,6 +720,14 @@ restart: if (i == r) IWL_DEBUG_RX(trans, "HW = SW = %d\n", r); + /* calculate total frames need to be restock after handling RX */ + total_empty = r - rxq->write_actual; + if (total_empty < 0) + total_empty += RX_QUEUE_SIZE; + + if (total_empty > (RX_QUEUE_SIZE / 2)) + fill_rx = 1; + while (i != r) { struct iwl_rx_mem_buffer *rxb; @@ -968,48 +739,29 @@ restart: iwl_pcie_rx_handle_rb(trans, rxb); i = (i + 1) & RX_QUEUE_MASK; - - /* If we have RX_CLAIM_REQ_ALLOC released rx buffers - - * try to claim the pre-allocated buffers from the allocator */ - if (rxq->used_count >= RX_CLAIM_REQ_ALLOC) { - struct iwl_rb_allocator *rba = &trans_pcie->rba; - struct iwl_rx_mem_buffer *out[RX_CLAIM_REQ_ALLOC]; - - /* Add the remaining 6 empty RBDs for allocator use */ - spin_lock(&rba->lock); - list_splice_tail_init(&rxq->rx_used, &rba->rbd_empty); - spin_unlock(&rba->lock); - - /* If not ready - continue, will try to reclaim later. - * No need to reschedule work - allocator exits only on - * success */ - if (!iwl_pcie_rx_allocator_get(trans, out)) { - /* If success - then RX_CLAIM_REQ_ALLOC - * buffers were retrieved and should be added - * to free list */ - rxq->used_count -= RX_CLAIM_REQ_ALLOC; - for (j = 0; j < RX_CLAIM_REQ_ALLOC; j++) { - list_add_tail(&out[j]->list, - &rxq->rx_free); - rxq->free_count++; - } + /* If there are a lot of unused frames, + * restock the Rx queue so ucode wont assert. */ + if (fill_rx) { + count++; + if (count >= 8) { + rxq->read = i; + spin_unlock(&rxq->lock); + iwl_pcie_rx_replenish(trans, GFP_ATOMIC); + count = 0; + goto restart; } } - /* handle restock for two cases: - * - we just pulled buffers from the allocator - * - we have 8+ unstolen pages accumulated */ - if (rxq->free_count >= RX_CLAIM_REQ_ALLOC) { - rxq->read = i; - spin_unlock(&rxq->lock); - iwl_pcie_rxq_restock(trans); - goto restart; - } } /* Backtrack one entry */ rxq->read = i; spin_unlock(&rxq->lock); + if (fill_rx) + iwl_pcie_rx_replenish(trans, GFP_ATOMIC); + else + iwl_pcie_rxq_restock(trans); + if (trans_pcie->napi.poll) napi_gro_flush(&trans_pcie->napi, false); } diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 43ae658af6ec..6203c4ad9bba 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -182,7 +182,7 @@ static void iwl_trans_pcie_write_shr(struct iwl_trans *trans, u32 reg, u32 val) static void iwl_pcie_set_pwr(struct iwl_trans *trans, bool vaux) { - if (!trans->cfg->apmg_not_supported) + if (trans->cfg->apmg_not_supported) return; if (vaux && pci_pme_capable(to_pci_dev(trans->dev), PCI_D3cold)) @@ -2459,7 +2459,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, struct iwl_trans_pcie *trans_pcie; struct iwl_trans *trans; u16 pci_cmd; - int err; + int ret; trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie), &pdev->dev, cfg, &trans_ops_pcie, 0); @@ -2474,8 +2474,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, spin_lock_init(&trans_pcie->ref_lock); init_waitqueue_head(&trans_pcie->ucode_write_waitq); - err = pci_enable_device(pdev); - if (err) + ret = pci_enable_device(pdev); + if (ret) goto out_no_pci; if (!cfg->base_params->pcie_l1_allowed) { @@ -2491,23 +2491,23 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, pci_set_master(pdev); - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); - if (!err) - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36)); - if (err) { - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (!err) - err = pci_set_consistent_dma_mask(pdev, + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); + if (!ret) + ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36)); + if (ret) { + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (!ret) + ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); /* both attempts failed: */ - if (err) { + if (ret) { dev_err(&pdev->dev, "No suitable DMA available\n"); goto out_pci_disable_device; } } - err = pci_request_regions(pdev, DRV_NAME); - if (err) { + ret = pci_request_regions(pdev, DRV_NAME); + if (ret) { dev_err(&pdev->dev, "pci_request_regions failed\n"); goto out_pci_disable_device; } @@ -2515,7 +2515,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, trans_pcie->hw_base = pci_ioremap_bar(pdev, 0); if (!trans_pcie->hw_base) { dev_err(&pdev->dev, "pci_ioremap_bar failed\n"); - err = -ENODEV; + ret = -ENODEV; goto out_pci_release_regions; } @@ -2527,9 +2527,9 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, trans_pcie->pci_dev = pdev; iwl_disable_interrupts(trans); - err = pci_enable_msi(pdev); - if (err) { - dev_err(&pdev->dev, "pci_enable_msi failed(0X%x)\n", err); + ret = pci_enable_msi(pdev); + if (ret) { + dev_err(&pdev->dev, "pci_enable_msi failed(0X%x)\n", ret); /* enable rfkill interrupt: hw bug w/a */ pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { @@ -2547,11 +2547,16 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, */ if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) { unsigned long flags; - int ret; trans->hw_rev = (trans->hw_rev & 0xfff0) | (CSR_HW_REV_STEP(trans->hw_rev << 2) << 2); + ret = iwl_pcie_prepare_card_hw(trans); + if (ret) { + IWL_WARN(trans, "Exit HW not ready\n"); + goto out_pci_disable_msi; + } + /* * in-order to recognize C step driver should read chip version * id located at the AUX bus MISC address space. @@ -2591,13 +2596,14 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, /* Initialize the wait queue for commands */ init_waitqueue_head(&trans_pcie->wait_command_queue); - if (iwl_pcie_alloc_ict(trans)) + ret = iwl_pcie_alloc_ict(trans); + if (ret) goto out_pci_disable_msi; - err = request_threaded_irq(pdev->irq, iwl_pcie_isr, + ret = request_threaded_irq(pdev->irq, iwl_pcie_isr, iwl_pcie_irq_handler, IRQF_SHARED, DRV_NAME, trans); - if (err) { + if (ret) { IWL_ERR(trans, "Error allocating IRQ %d\n", pdev->irq); goto out_free_ict; } @@ -2617,5 +2623,5 @@ out_pci_disable_device: pci_disable_device(pdev); out_no_pci: iwl_trans_free(trans); - return ERR_PTR(err); + return ERR_PTR(ret); } diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 880d0d63e872..7d50711476fe 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -1566,13 +1566,13 @@ static inline void xenvif_tx_dealloc_action(struct xenvif_queue *queue) smp_rmb(); while (dc != dp) { - BUG_ON(gop - queue->tx_unmap_ops > MAX_PENDING_REQS); + BUG_ON(gop - queue->tx_unmap_ops >= MAX_PENDING_REQS); pending_idx = queue->dealloc_ring[pending_index(dc++)]; - pending_idx_release[gop-queue->tx_unmap_ops] = + pending_idx_release[gop - queue->tx_unmap_ops] = pending_idx; - queue->pages_to_unmap[gop-queue->tx_unmap_ops] = + queue->pages_to_unmap[gop - queue->tx_unmap_ops] = queue->mmap_pages[pending_idx]; gnttab_set_unmap_op(gop, idx_to_kaddr(queue, pending_idx), diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index 8eb22c0ca7ce..7e2c43f701bc 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -535,8 +535,6 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm, __func__, dimm_name, cmd_name, i); return -ENXIO; } - if (!access_ok(VERIFY_READ, p + in_len, in_size)) - return -EFAULT; if (in_len < sizeof(in_env)) copy = min_t(u32, sizeof(in_env) - in_len, in_size); else @@ -557,8 +555,6 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm, __func__, dimm_name, cmd_name, i); return -EFAULT; } - if (!access_ok(VERIFY_WRITE, p + in_len + out_len, out_size)) - return -EFAULT; if (out_len < sizeof(out_env)) copy = min_t(u32, sizeof(out_env) - out_len, out_size); else @@ -570,9 +566,6 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm, } buf_len = out_len + in_len; - if (!access_ok(VERIFY_WRITE, p, sizeof(buf_len))) - return -EFAULT; - if (buf_len > ND_IOCTL_MAX_BUFLEN) { dev_dbg(dev, "%s:%s cmd: %s buf_len: %zu > %d\n", __func__, dimm_name, cmd_name, buf_len, @@ -706,8 +699,10 @@ int __init nvdimm_bus_init(void) nvdimm_major = rc; nd_class = class_create(THIS_MODULE, "nd"); - if (IS_ERR(nd_class)) + if (IS_ERR(nd_class)) { + rc = PTR_ERR(nd_class); goto err_class; + } return 0; diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c index a5233422f9dc..7384455792bf 100644 --- a/drivers/nvdimm/region_devs.c +++ b/drivers/nvdimm/region_devs.c @@ -458,10 +458,15 @@ static void nd_region_notify_driver_action(struct nvdimm_bus *nvdimm_bus, nvdimm_bus_unlock(dev); } if (is_nd_btt(dev) && probe) { + struct nd_btt *nd_btt = to_nd_btt(dev); + nd_region = to_nd_region(dev->parent); nvdimm_bus_lock(dev); if (nd_region->btt_seed == dev) nd_region_create_btt_seed(nd_region); + if (nd_region->ns_seed == &nd_btt->ndns->dev && + is_nd_blk(dev->parent)) + nd_region_create_blk_seed(nd_region); nvdimm_bus_unlock(dev); } } diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 8df1b1777745..59bb8556e43a 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -47,7 +47,7 @@ config OF_DYNAMIC config OF_ADDRESS def_bool y - depends on !SPARC + depends on !SPARC && HAS_IOMEM select OF_ADDRESS_PCI if PCI config OF_ADDRESS_PCI diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 18016341d5a9..9f71770b6226 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -979,7 +979,6 @@ static struct platform_driver unittest_driver = { .remove = unittest_remove, .driver = { .name = "unittest", - .owner = THIS_MODULE, .of_match_table = of_match_ptr(unittest_match), }, }; @@ -1666,7 +1665,6 @@ static const struct i2c_device_id unittest_i2c_dev_id[] = { static struct i2c_driver unittest_i2c_dev_driver = { .driver = { .name = "unittest-i2c-dev", - .owner = THIS_MODULE, }, .probe = unittest_i2c_dev_probe, .remove = unittest_i2c_dev_remove, @@ -1761,7 +1759,6 @@ static const struct i2c_device_id unittest_i2c_mux_id[] = { static struct i2c_driver unittest_i2c_mux_driver = { .driver = { .name = "unittest-i2c-mux", - .owner = THIS_MODULE, }, .probe = unittest_i2c_mux_probe, .remove = unittest_i2c_mux_remove, diff --git a/drivers/parport/share.c b/drivers/parport/share.c index 8067f54ce050..5ce5ef211bdb 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c @@ -891,8 +891,10 @@ parport_register_dev_model(struct parport *port, const char *name, par_dev->dev.release = free_pardevice; par_dev->devmodel = true; ret = device_register(&par_dev->dev); - if (ret) - goto err_put_dev; + if (ret) { + put_device(&par_dev->dev); + goto err_put_port; + } /* Chain this onto the list */ par_dev->prev = NULL; @@ -907,7 +909,8 @@ parport_register_dev_model(struct parport *port, const char *name, spin_unlock(&port->physport->pardevice_lock); pr_debug("%s: cannot grant exclusive access for device %s\n", port->name, name); - goto err_put_dev; + device_unregister(&par_dev->dev); + goto err_put_port; } port->flags |= PARPORT_FLAG_EXCL; } @@ -938,8 +941,6 @@ parport_register_dev_model(struct parport *port, const char *name, return par_dev; -err_put_dev: - put_device(&par_dev->dev); err_free_devname: kfree(devname); err_free_par_dev: diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index c0e6ede3e27d..6b8dd162f644 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -56,6 +56,7 @@ config PHY_EXYNOS_MIPI_VIDEO config PHY_PXA_28NM_HSIC tristate "Marvell USB HSIC 28nm PHY Driver" + depends on HAS_IOMEM select GENERIC_PHY help Enable this to support Marvell USB HSIC PHY driver for Marvell @@ -66,6 +67,7 @@ config PHY_PXA_28NM_HSIC config PHY_PXA_28NM_USB2 tristate "Marvell USB 2.0 28nm PHY Driver" + depends on HAS_IOMEM select GENERIC_PHY help Enable this to support Marvell USB 2.0 PHY driver for Marvell diff --git a/drivers/phy/phy-berlin-usb.c b/drivers/phy/phy-berlin-usb.c index c6fc95b53083..335e06d66ed9 100644 --- a/drivers/phy/phy-berlin-usb.c +++ b/drivers/phy/phy-berlin-usb.c @@ -105,9 +105,9 @@ static const u32 phy_berlin_pll_dividers[] = { /* Berlin 2 */ - CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54), - /* Berlin 2CD */ CLK_REF_DIV(0x6) | FEEDBACK_CLK_DIV(0x55), + /* Berlin 2CD/Q */ + CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54), }; struct phy_berlin_usb_priv { diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c index e17c539e4f6f..2dad7e820ff0 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/phy-sun4i-usb.c @@ -212,6 +212,7 @@ void sun4i_usb_phy_set_squelch_detect(struct phy *_phy, bool enabled) sun4i_usb_phy_write(phy, PHY_SQUELCH_DETECT, enabled ? 0 : 2, 2); } +EXPORT_SYMBOL_GPL(sun4i_usb_phy_set_squelch_detect); static struct phy_ops sun4i_usb_phy_ops = { .init = sun4i_usb_phy_init, diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c index 53f295c1bab1..08020dc2c7c8 100644 --- a/drivers/phy/phy-ti-pipe3.c +++ b/drivers/phy/phy-ti-pipe3.c @@ -28,7 +28,8 @@ #include <linux/delay.h> #include <linux/phy/omap_control_phy.h> #include <linux/of_platform.h> -#include <linux/spinlock.h> +#include <linux/mfd/syscon.h> +#include <linux/regmap.h> #define PLL_STATUS 0x00000004 #define PLL_GO 0x00000008 @@ -53,6 +54,8 @@ #define PLL_LOCK 0x2 #define PLL_IDLE 0x1 +#define SATA_PLL_SOFT_RESET BIT(18) + /* * This is an Empirical value that works, need to confirm the actual * value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status @@ -83,10 +86,9 @@ struct ti_pipe3 { struct clk *refclk; struct clk *div_clk; struct pipe3_dpll_map *dpll_map; - bool enabled; - spinlock_t lock; /* serialize clock enable/disable */ - /* the below flag is needed specifically for SATA */ - bool refclk_enabled; + struct regmap *dpll_reset_syscon; /* ctrl. reg. acces */ + unsigned int dpll_reset_reg; /* reg. index within syscon */ + bool sata_refclk_enabled; }; static struct pipe3_dpll_map dpll_map_usb[] = { @@ -137,6 +139,9 @@ static struct pipe3_dpll_params *ti_pipe3_get_dpll_params(struct ti_pipe3 *phy) return NULL; } +static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy); +static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy); + static int ti_pipe3_power_off(struct phy *x) { struct ti_pipe3 *phy = phy_get_drvdata(x); @@ -217,6 +222,7 @@ static int ti_pipe3_init(struct phy *x) u32 val; int ret = 0; + ti_pipe3_enable_clocks(phy); /* * Set pcie_pcs register to 0x96 for proper functioning of phy * as recommended in AM572x TRM SPRUHZ6, section 18.5.2.2, table @@ -250,33 +256,46 @@ static int ti_pipe3_exit(struct phy *x) u32 val; unsigned long timeout; - /* SATA DPLL can't be powered down due to Errata i783 and PCIe - * does not have internal DPLL + /* If dpll_reset_syscon is not present we wont power down SATA DPLL + * due to Errata i783 */ - if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata") || - of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) + if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata") && + !phy->dpll_reset_syscon) return 0; - /* Put DPLL in IDLE mode */ - val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); - val |= PLL_IDLE; - ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); + /* PCIe doesn't have internal DPLL */ + if (!of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) { + /* Put DPLL in IDLE mode */ + val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); + val |= PLL_IDLE; + ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); - /* wait for LDO and Oscillator to power down */ - timeout = jiffies + msecs_to_jiffies(PLL_IDLE_TIME); - do { - cpu_relax(); - val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS); - if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN)) - break; - } while (!time_after(jiffies, timeout)); + /* wait for LDO and Oscillator to power down */ + timeout = jiffies + msecs_to_jiffies(PLL_IDLE_TIME); + do { + cpu_relax(); + val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS); + if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN)) + break; + } while (!time_after(jiffies, timeout)); + + if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) { + dev_err(phy->dev, "Failed to power down: PLL_STATUS 0x%x\n", + val); + return -EBUSY; + } + } - if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) { - dev_err(phy->dev, "Failed to power down: PLL_STATUS 0x%x\n", - val); - return -EBUSY; + /* i783: SATA needs control bit toggle after PLL unlock */ + if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata")) { + regmap_update_bits(phy->dpll_reset_syscon, phy->dpll_reset_reg, + SATA_PLL_SOFT_RESET, SATA_PLL_SOFT_RESET); + regmap_update_bits(phy->dpll_reset_syscon, phy->dpll_reset_reg, + SATA_PLL_SOFT_RESET, 0); } + ti_pipe3_disable_clocks(phy); + return 0; } static struct phy_ops ops = { @@ -306,7 +325,6 @@ static int ti_pipe3_probe(struct platform_device *pdev) return -ENOMEM; phy->dev = &pdev->dev; - spin_lock_init(&phy->lock); if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { match = of_match_device(ti_pipe3_id_table, &pdev->dev); @@ -350,6 +368,21 @@ static int ti_pipe3_probe(struct platform_device *pdev) } } else { phy->wkupclk = ERR_PTR(-ENODEV); + phy->dpll_reset_syscon = syscon_regmap_lookup_by_phandle(node, + "syscon-pllreset"); + if (IS_ERR(phy->dpll_reset_syscon)) { + dev_info(&pdev->dev, + "can't get syscon-pllreset, sata dpll won't idle\n"); + phy->dpll_reset_syscon = NULL; + } else { + if (of_property_read_u32_index(node, + "syscon-pllreset", 1, + &phy->dpll_reset_reg)) { + dev_err(&pdev->dev, + "couldn't get pllreset reg. offset\n"); + return -EINVAL; + } + } } if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { @@ -403,6 +436,16 @@ static int ti_pipe3_probe(struct platform_device *pdev) platform_set_drvdata(pdev, phy); pm_runtime_enable(phy->dev); + /* + * Prevent auto-disable of refclk for SATA PHY due to Errata i783 + */ + if (of_device_is_compatible(node, "ti,phy-pipe3-sata")) { + if (!IS_ERR(phy->refclk)) { + clk_prepare_enable(phy->refclk); + phy->sata_refclk_enabled = true; + } + } + generic_phy = devm_phy_create(phy->dev, NULL, &ops); if (IS_ERR(generic_phy)) return PTR_ERR(generic_phy); @@ -413,63 +456,33 @@ static int ti_pipe3_probe(struct platform_device *pdev) if (IS_ERR(phy_provider)) return PTR_ERR(phy_provider); - pm_runtime_get(&pdev->dev); - return 0; } static int ti_pipe3_remove(struct platform_device *pdev) { - if (!pm_runtime_suspended(&pdev->dev)) - pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); return 0; } -#ifdef CONFIG_PM -static int ti_pipe3_enable_refclk(struct ti_pipe3 *phy) +static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy) { - if (!IS_ERR(phy->refclk) && !phy->refclk_enabled) { - int ret; + int ret = 0; + if (!IS_ERR(phy->refclk)) { ret = clk_prepare_enable(phy->refclk); if (ret) { dev_err(phy->dev, "Failed to enable refclk %d\n", ret); return ret; } - phy->refclk_enabled = true; } - return 0; -} - -static void ti_pipe3_disable_refclk(struct ti_pipe3 *phy) -{ - if (!IS_ERR(phy->refclk)) - clk_disable_unprepare(phy->refclk); - - phy->refclk_enabled = false; -} - -static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy) -{ - int ret = 0; - unsigned long flags; - - spin_lock_irqsave(&phy->lock, flags); - if (phy->enabled) - goto err1; - - ret = ti_pipe3_enable_refclk(phy); - if (ret) - goto err1; - if (!IS_ERR(phy->wkupclk)) { ret = clk_prepare_enable(phy->wkupclk); if (ret) { dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret); - goto err2; + goto disable_refclk; } } @@ -477,96 +490,43 @@ static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy) ret = clk_prepare_enable(phy->div_clk); if (ret) { dev_err(phy->dev, "Failed to enable div_clk %d\n", ret); - goto err3; + goto disable_wkupclk; } } - phy->enabled = true; - spin_unlock_irqrestore(&phy->lock, flags); return 0; -err3: +disable_wkupclk: if (!IS_ERR(phy->wkupclk)) clk_disable_unprepare(phy->wkupclk); -err2: +disable_refclk: if (!IS_ERR(phy->refclk)) clk_disable_unprepare(phy->refclk); - ti_pipe3_disable_refclk(phy); -err1: - spin_unlock_irqrestore(&phy->lock, flags); return ret; } static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy) { - unsigned long flags; - - spin_lock_irqsave(&phy->lock, flags); - if (!phy->enabled) { - spin_unlock_irqrestore(&phy->lock, flags); - return; - } - if (!IS_ERR(phy->wkupclk)) clk_disable_unprepare(phy->wkupclk); - /* Don't disable refclk for SATA PHY due to Errata i783 */ - if (!of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata")) - ti_pipe3_disable_refclk(phy); + if (!IS_ERR(phy->refclk)) { + clk_disable_unprepare(phy->refclk); + /* + * SATA refclk needs an additional disable as we left it + * on in probe to avoid Errata i783 + */ + if (phy->sata_refclk_enabled) { + clk_disable_unprepare(phy->refclk); + phy->sata_refclk_enabled = false; + } + } + if (!IS_ERR(phy->div_clk)) clk_disable_unprepare(phy->div_clk); - phy->enabled = false; - spin_unlock_irqrestore(&phy->lock, flags); } -static int ti_pipe3_runtime_suspend(struct device *dev) -{ - struct ti_pipe3 *phy = dev_get_drvdata(dev); - - ti_pipe3_disable_clocks(phy); - return 0; -} - -static int ti_pipe3_runtime_resume(struct device *dev) -{ - struct ti_pipe3 *phy = dev_get_drvdata(dev); - int ret = 0; - - ret = ti_pipe3_enable_clocks(phy); - return ret; -} - -static int ti_pipe3_suspend(struct device *dev) -{ - struct ti_pipe3 *phy = dev_get_drvdata(dev); - - ti_pipe3_disable_clocks(phy); - return 0; -} - -static int ti_pipe3_resume(struct device *dev) -{ - struct ti_pipe3 *phy = dev_get_drvdata(dev); - int ret; - - ret = ti_pipe3_enable_clocks(phy); - if (ret) - return ret; - - pm_runtime_disable(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - return 0; -} -#endif - -static const struct dev_pm_ops ti_pipe3_pm_ops = { - SET_RUNTIME_PM_OPS(ti_pipe3_runtime_suspend, - ti_pipe3_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(ti_pipe3_suspend, ti_pipe3_resume) -}; - static const struct of_device_id ti_pipe3_id_table[] = { { .compatible = "ti,phy-usb3", @@ -592,7 +552,6 @@ static struct platform_driver ti_pipe3_driver = { .remove = ti_pipe3_remove, .driver = { .name = "ti-pipe3", - .pm = &ti_pipe3_pm_ops, .of_match_table = ti_pipe3_id_table, }, }; diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index efcf2a2b3975..6177315ab74e 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -473,6 +473,8 @@ static void bcm2835_gpio_irq_disable(struct irq_data *data) spin_lock_irqsave(&pc->irq_lock[bank], flags); bcm2835_gpio_irq_config(pc, gpio, false); + /* Clear events that were latched prior to clearing event sources */ + bcm2835_gpio_set_bit(pc, GPEDS0, gpio); clear_bit(offset, &pc->enabled_irq_map[bank]); spin_unlock_irqrestore(&pc->irq_lock[bank], flags); } diff --git a/drivers/pinctrl/freescale/pinctrl-imx1-core.c b/drivers/pinctrl/freescale/pinctrl-imx1-core.c index 5fd4437cee15..88a7fac11bd4 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx1-core.c +++ b/drivers/pinctrl/freescale/pinctrl-imx1-core.c @@ -403,14 +403,13 @@ static int imx1_pinconf_set(struct pinctrl_dev *pctldev, unsigned num_configs) { struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); - const struct imx1_pinctrl_soc_info *info = ipctl->info; int i; for (i = 0; i != num_configs; ++i) { imx1_write_bit(ipctl, pin_id, configs[i] & 0x01, MX1_PUEN); dev_dbg(ipctl->dev, "pinconf set pullup pin %s\n", - info->pins[pin_id].name); + pin_desc_get(pctldev, pin_id)->name); } return 0; diff --git a/drivers/pinctrl/nomadik/pinctrl-abx500.c b/drivers/pinctrl/nomadik/pinctrl-abx500.c index 557d0f2a3031..97681fac082e 100644 --- a/drivers/pinctrl/nomadik/pinctrl-abx500.c +++ b/drivers/pinctrl/nomadik/pinctrl-abx500.c @@ -787,7 +787,6 @@ static const struct pinmux_ops abx500_pinmux_ops = { .set_mux = abx500_pmx_set, .gpio_request_enable = abx500_gpio_request_enable, .gpio_disable_free = abx500_gpio_disable_free, - .strict = true, }; static int abx500_get_groups_cnt(struct pinctrl_dev *pctldev) diff --git a/drivers/pinctrl/pinctrl-lpc18xx.c b/drivers/pinctrl/pinctrl-lpc18xx.c index ef0b697639a7..347c763a6a78 100644 --- a/drivers/pinctrl/pinctrl-lpc18xx.c +++ b/drivers/pinctrl/pinctrl-lpc18xx.c @@ -823,7 +823,7 @@ static int lpc18xx_pconf_set_i2c0(struct pinctrl_dev *pctldev, break; case PIN_CONFIG_INPUT_SCHMITT_ENABLE: - if (param) + if (param_val) *reg &= ~(LPC18XX_SCU_I2C0_ZIF << shift); else *reg |= (LPC18XX_SCU_I2C0_ZIF << shift); @@ -876,7 +876,7 @@ static int lpc18xx_pconf_set_pin(struct pinctrl_dev *pctldev, break; case PIN_CONFIG_INPUT_SCHMITT_ENABLE: - if (param) + if (param_val) *reg &= ~LPC18XX_SCU_PIN_ZIF; else *reg |= LPC18XX_SCU_PIN_ZIF; diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index b2de09d3b1a0..0b8d480171a3 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -1760,7 +1760,8 @@ static int pcs_irq_init_chained_handler(struct pcs_device *pcs, int res; res = request_irq(pcs_soc->irq, pcs_irq_handler, - IRQF_SHARED | IRQF_NO_SUSPEND, + IRQF_SHARED | IRQF_NO_SUSPEND | + IRQF_NO_THREAD, name, pcs_soc); if (res) { pcs_soc->irq = -1; diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index 3dd5a3b2ac62..c760bf43d116 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -33,11 +33,6 @@ #include "../core.h" #include "pinctrl-samsung.h" -#define GROUP_SUFFIX "-grp" -#define GSUFFIX_LEN sizeof(GROUP_SUFFIX) -#define FUNCTION_SUFFIX "-mux" -#define FSUFFIX_LEN sizeof(FUNCTION_SUFFIX) - /* list of all possible config options supported */ static struct pin_config { const char *property; diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h index c7508d5f6886..0874cfee6889 100644 --- a/drivers/pinctrl/sh-pfc/sh_pfc.h +++ b/drivers/pinctrl/sh-pfc/sh_pfc.h @@ -224,7 +224,7 @@ struct sh_pfc_soc_info { /* PINMUX_GPIO_GP_ALL - Expand to a list of sh_pfc_pin entries */ #define _GP_GPIO(bank, _pin, _name, sfx) \ - [(bank * 32) + _pin] = { \ + { \ .pin = (bank * 32) + _pin, \ .name = __stringify(_name), \ .enum_id = _name##_DATA, \ diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c index f87a5eaf75da..0afaf79a4e51 100644 --- a/drivers/pinctrl/spear/pinctrl-spear.c +++ b/drivers/pinctrl/spear/pinctrl-spear.c @@ -2,7 +2,7 @@ * Driver for the ST Microelectronics SPEAr pinmux * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * Inspired from: * - U300 Pinctl drivers diff --git a/drivers/pinctrl/spear/pinctrl-spear.h b/drivers/pinctrl/spear/pinctrl-spear.h index dc8bf85ecb2a..27c2cc8d83ad 100644 --- a/drivers/pinctrl/spear/pinctrl-spear.h +++ b/drivers/pinctrl/spear/pinctrl-spear.h @@ -2,7 +2,7 @@ * Driver header file for the ST Microelectronics SPEAr pinmux * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/pinctrl/spear/pinctrl-spear1310.c b/drivers/pinctrl/spear/pinctrl-spear1310.c index a7bdc537efa7..92611bb757ac 100644 --- a/drivers/pinctrl/spear/pinctrl-spear1310.c +++ b/drivers/pinctrl/spear/pinctrl-spear1310.c @@ -2,7 +2,7 @@ * Driver for the ST Microelectronics SPEAr1310 pinmux * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -2730,7 +2730,7 @@ static void __exit spear1310_pinctrl_exit(void) } module_exit(spear1310_pinctrl_exit); -MODULE_AUTHOR("Viresh Kumar <viresh.linux@gmail.com>"); +MODULE_AUTHOR("Viresh Kumar <vireshk@kernel.org>"); MODULE_DESCRIPTION("ST Microelectronics SPEAr1310 pinctrl driver"); MODULE_LICENSE("GPL v2"); MODULE_DEVICE_TABLE(of, spear1310_pinctrl_of_match); diff --git a/drivers/pinctrl/spear/pinctrl-spear1340.c b/drivers/pinctrl/spear/pinctrl-spear1340.c index f43ec85a0328..f842e9dc40d0 100644 --- a/drivers/pinctrl/spear/pinctrl-spear1340.c +++ b/drivers/pinctrl/spear/pinctrl-spear1340.c @@ -2,7 +2,7 @@ * Driver for the ST Microelectronics SPEAr1340 pinmux * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -2046,7 +2046,7 @@ static void __exit spear1340_pinctrl_exit(void) } module_exit(spear1340_pinctrl_exit); -MODULE_AUTHOR("Viresh Kumar <viresh.linux@gmail.com>"); +MODULE_AUTHOR("Viresh Kumar <vireshk@kernel.org>"); MODULE_DESCRIPTION("ST Microelectronics SPEAr1340 pinctrl driver"); MODULE_LICENSE("GPL v2"); MODULE_DEVICE_TABLE(of, spear1340_pinctrl_of_match); diff --git a/drivers/pinctrl/spear/pinctrl-spear300.c b/drivers/pinctrl/spear/pinctrl-spear300.c index da8990a8eeef..d998a2ccff48 100644 --- a/drivers/pinctrl/spear/pinctrl-spear300.c +++ b/drivers/pinctrl/spear/pinctrl-spear300.c @@ -2,7 +2,7 @@ * Driver for the ST Microelectronics SPEAr300 pinmux * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -703,7 +703,7 @@ static void __exit spear300_pinctrl_exit(void) } module_exit(spear300_pinctrl_exit); -MODULE_AUTHOR("Viresh Kumar <viresh.linux@gmail.com>"); +MODULE_AUTHOR("Viresh Kumar <vireshk@kernel.org>"); MODULE_DESCRIPTION("ST Microelectronics SPEAr300 pinctrl driver"); MODULE_LICENSE("GPL v2"); MODULE_DEVICE_TABLE(of, spear300_pinctrl_of_match); diff --git a/drivers/pinctrl/spear/pinctrl-spear310.c b/drivers/pinctrl/spear/pinctrl-spear310.c index 31ede51e819b..609b18aceb16 100644 --- a/drivers/pinctrl/spear/pinctrl-spear310.c +++ b/drivers/pinctrl/spear/pinctrl-spear310.c @@ -2,7 +2,7 @@ * Driver for the ST Microelectronics SPEAr310 pinmux * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -426,7 +426,7 @@ static void __exit spear310_pinctrl_exit(void) } module_exit(spear310_pinctrl_exit); -MODULE_AUTHOR("Viresh Kumar <viresh.linux@gmail.com>"); +MODULE_AUTHOR("Viresh Kumar <vireshk@kernel.org>"); MODULE_DESCRIPTION("ST Microelectronics SPEAr310 pinctrl driver"); MODULE_LICENSE("GPL v2"); MODULE_DEVICE_TABLE(of, spear310_pinctrl_of_match); diff --git a/drivers/pinctrl/spear/pinctrl-spear320.c b/drivers/pinctrl/spear/pinctrl-spear320.c index 506e40b641e0..c07114431bd4 100644 --- a/drivers/pinctrl/spear/pinctrl-spear320.c +++ b/drivers/pinctrl/spear/pinctrl-spear320.c @@ -2,7 +2,7 @@ * Driver for the ST Microelectronics SPEAr320 pinmux * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -3467,7 +3467,7 @@ static void __exit spear320_pinctrl_exit(void) } module_exit(spear320_pinctrl_exit); -MODULE_AUTHOR("Viresh Kumar <viresh.linux@gmail.com>"); +MODULE_AUTHOR("Viresh Kumar <vireshk@kernel.org>"); MODULE_DESCRIPTION("ST Microelectronics SPEAr320 pinctrl driver"); MODULE_LICENSE("GPL v2"); MODULE_DEVICE_TABLE(of, spear320_pinctrl_of_match); diff --git a/drivers/pinctrl/spear/pinctrl-spear3xx.c b/drivers/pinctrl/spear/pinctrl-spear3xx.c index 12ee21af766b..d3119aafe709 100644 --- a/drivers/pinctrl/spear/pinctrl-spear3xx.c +++ b/drivers/pinctrl/spear/pinctrl-spear3xx.c @@ -2,7 +2,7 @@ * Driver for the ST Microelectronics SPEAr3xx pinmux * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/pinctrl/spear/pinctrl-spear3xx.h b/drivers/pinctrl/spear/pinctrl-spear3xx.h index 7860b36053c4..ce19dcf8f08b 100644 --- a/drivers/pinctrl/spear/pinctrl-spear3xx.h +++ b/drivers/pinctrl/spear/pinctrl-spear3xx.h @@ -2,7 +2,7 @@ * Header file for the ST Microelectronics SPEAr3xx pinmux * * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index ed317ccac4a2..aaeeae81e3a9 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -309,12 +309,15 @@ static const struct dmi_system_id dell_quirks[] __initconst = { static struct calling_interface_buffer *buffer; static DEFINE_MUTEX(buffer_mutex); -static int hwswitch_state; +static void clear_buffer(void) +{ + memset(buffer, 0, sizeof(struct calling_interface_buffer)); +} static void get_buffer(void) { mutex_lock(&buffer_mutex); - memset(buffer, 0, sizeof(struct calling_interface_buffer)); + clear_buffer(); } static void release_buffer(void) @@ -548,21 +551,41 @@ static int dell_rfkill_set(void *data, bool blocked) int disable = blocked ? 1 : 0; unsigned long radio = (unsigned long)data; int hwswitch_bit = (unsigned long)data - 1; + int hwswitch; + int status; + int ret; get_buffer(); + + dell_send_request(buffer, 17, 11); + ret = buffer->output[0]; + status = buffer->output[1]; + + if (ret != 0) + goto out; + + clear_buffer(); + + buffer->input[0] = 0x2; dell_send_request(buffer, 17, 11); + ret = buffer->output[0]; + hwswitch = buffer->output[1]; /* If the hardware switch controls this radio, and the hardware switch is disabled, always disable the radio */ - if ((hwswitch_state & BIT(hwswitch_bit)) && - !(buffer->output[1] & BIT(16))) + if (ret == 0 && (hwswitch & BIT(hwswitch_bit)) && + (status & BIT(0)) && !(status & BIT(16))) disable = 1; + clear_buffer(); + buffer->input[0] = (1 | (radio<<8) | (disable << 16)); dell_send_request(buffer, 17, 11); + ret = buffer->output[0]; + out: release_buffer(); - return 0; + return dell_smi_error(ret); } /* Must be called with the buffer held */ @@ -572,6 +595,7 @@ static void dell_rfkill_update_sw_state(struct rfkill *rfkill, int radio, if (status & BIT(0)) { /* Has hw-switch, sync sw_state to BIOS */ int block = rfkill_blocked(rfkill); + clear_buffer(); buffer->input[0] = (1 | (radio << 8) | (block << 16)); dell_send_request(buffer, 17, 11); } else { @@ -581,23 +605,43 @@ static void dell_rfkill_update_sw_state(struct rfkill *rfkill, int radio, } static void dell_rfkill_update_hw_state(struct rfkill *rfkill, int radio, - int status) + int status, int hwswitch) { - if (hwswitch_state & (BIT(radio - 1))) + if (hwswitch & (BIT(radio - 1))) rfkill_set_hw_state(rfkill, !(status & BIT(16))); } static void dell_rfkill_query(struct rfkill *rfkill, void *data) { + int radio = ((unsigned long)data & 0xF); + int hwswitch; int status; + int ret; get_buffer(); + dell_send_request(buffer, 17, 11); + ret = buffer->output[0]; status = buffer->output[1]; - dell_rfkill_update_hw_state(rfkill, (unsigned long)data, status); + if (ret != 0 || !(status & BIT(0))) { + release_buffer(); + return; + } + + clear_buffer(); + + buffer->input[0] = 0x2; + dell_send_request(buffer, 17, 11); + ret = buffer->output[0]; + hwswitch = buffer->output[1]; release_buffer(); + + if (ret != 0) + return; + + dell_rfkill_update_hw_state(rfkill, radio, status, hwswitch); } static const struct rfkill_ops dell_rfkill_ops = { @@ -609,13 +653,27 @@ static struct dentry *dell_laptop_dir; static int dell_debugfs_show(struct seq_file *s, void *data) { + int hwswitch_state; + int hwswitch_ret; int status; + int ret; get_buffer(); + dell_send_request(buffer, 17, 11); + ret = buffer->output[0]; status = buffer->output[1]; + + clear_buffer(); + + buffer->input[0] = 0x2; + dell_send_request(buffer, 17, 11); + hwswitch_ret = buffer->output[0]; + hwswitch_state = buffer->output[1]; + release_buffer(); + seq_printf(s, "return:\t%d\n", ret); seq_printf(s, "status:\t0x%X\n", status); seq_printf(s, "Bit 0 : Hardware switch supported: %lu\n", status & BIT(0)); @@ -657,7 +715,8 @@ static int dell_debugfs_show(struct seq_file *s, void *data) seq_printf(s, "Bit 21: WiGig is blocked: %lu\n", (status & BIT(21)) >> 21); - seq_printf(s, "\nhwswitch_state:\t0x%X\n", hwswitch_state); + seq_printf(s, "\nhwswitch_return:\t%d\n", hwswitch_ret); + seq_printf(s, "hwswitch_state:\t0x%X\n", hwswitch_state); seq_printf(s, "Bit 0 : Wifi controlled by switch: %lu\n", hwswitch_state & BIT(0)); seq_printf(s, "Bit 1 : Bluetooth controlled by switch: %lu\n", @@ -693,25 +752,43 @@ static const struct file_operations dell_debugfs_fops = { static void dell_update_rfkill(struct work_struct *ignored) { + int hwswitch = 0; int status; + int ret; get_buffer(); + dell_send_request(buffer, 17, 11); + ret = buffer->output[0]; status = buffer->output[1]; + if (ret != 0) + goto out; + + clear_buffer(); + + buffer->input[0] = 0x2; + dell_send_request(buffer, 17, 11); + ret = buffer->output[0]; + + if (ret == 0 && (status & BIT(0))) + hwswitch = buffer->output[1]; + if (wifi_rfkill) { - dell_rfkill_update_hw_state(wifi_rfkill, 1, status); + dell_rfkill_update_hw_state(wifi_rfkill, 1, status, hwswitch); dell_rfkill_update_sw_state(wifi_rfkill, 1, status); } if (bluetooth_rfkill) { - dell_rfkill_update_hw_state(bluetooth_rfkill, 2, status); + dell_rfkill_update_hw_state(bluetooth_rfkill, 2, status, + hwswitch); dell_rfkill_update_sw_state(bluetooth_rfkill, 2, status); } if (wwan_rfkill) { - dell_rfkill_update_hw_state(wwan_rfkill, 3, status); + dell_rfkill_update_hw_state(wwan_rfkill, 3, status, hwswitch); dell_rfkill_update_sw_state(wwan_rfkill, 3, status); } + out: release_buffer(); } static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); @@ -773,21 +850,17 @@ static int __init dell_setup_rfkill(void) get_buffer(); dell_send_request(buffer, 17, 11); + ret = buffer->output[0]; status = buffer->output[1]; - buffer->input[0] = 0x2; - dell_send_request(buffer, 17, 11); - hwswitch_state = buffer->output[1]; release_buffer(); - if (!(status & BIT(0))) { - if (force_rfkill) { - /* No hwsitch, clear all hw-controlled bits */ - hwswitch_state &= ~7; - } else { - /* rfkill is only tested on laptops with a hwswitch */ - return 0; - } - } + /* dell wireless info smbios call is not supported */ + if (ret != 0) + return 0; + + /* rfkill is only tested on laptops with a hwswitch */ + if (!(status & BIT(0)) && !force_rfkill) + return 0; if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) { wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev, @@ -932,47 +1005,50 @@ static void dell_cleanup_rfkill(void) static int dell_send_intensity(struct backlight_device *bd) { - int ret = 0; + int token; + int ret; + + token = find_token_location(BRIGHTNESS_TOKEN); + if (token == -1) + return -ENODEV; get_buffer(); - buffer->input[0] = find_token_location(BRIGHTNESS_TOKEN); + buffer->input[0] = token; buffer->input[1] = bd->props.brightness; - if (buffer->input[0] == -1) { - ret = -ENODEV; - goto out; - } - if (power_supply_is_system_supplied() > 0) dell_send_request(buffer, 1, 2); else dell_send_request(buffer, 1, 1); - out: + ret = dell_smi_error(buffer->output[0]); + release_buffer(); return ret; } static int dell_get_intensity(struct backlight_device *bd) { - int ret = 0; + int token; + int ret; - get_buffer(); - buffer->input[0] = find_token_location(BRIGHTNESS_TOKEN); + token = find_token_location(BRIGHTNESS_TOKEN); + if (token == -1) + return -ENODEV; - if (buffer->input[0] == -1) { - ret = -ENODEV; - goto out; - } + get_buffer(); + buffer->input[0] = token; if (power_supply_is_system_supplied() > 0) dell_send_request(buffer, 0, 2); else dell_send_request(buffer, 0, 1); - ret = buffer->output[1]; + if (buffer->output[0]) + ret = dell_smi_error(buffer->output[0]); + else + ret = buffer->output[1]; - out: release_buffer(); return ret; } @@ -2036,6 +2112,7 @@ static void kbd_led_exit(void) static int __init dell_init(void) { int max_intensity = 0; + int token; int ret; if (!dmi_check_system(dell_device_table)) @@ -2094,13 +2171,15 @@ static int __init dell_init(void) if (acpi_video_get_backlight_type() != acpi_backlight_vendor) return 0; - get_buffer(); - buffer->input[0] = find_token_location(BRIGHTNESS_TOKEN); - if (buffer->input[0] != -1) { + token = find_token_location(BRIGHTNESS_TOKEN); + if (token != -1) { + get_buffer(); + buffer->input[0] = token; dell_send_request(buffer, 0, 2); - max_intensity = buffer->output[3]; + if (buffer->output[0] == 0) + max_intensity = buffer->output[3]; + release_buffer(); } - release_buffer(); if (max_intensity) { struct backlight_properties props; diff --git a/drivers/platform/x86/intel_pmc_ipc.c b/drivers/platform/x86/intel_pmc_ipc.c index d734763dab69..105cfffe82c6 100644 --- a/drivers/platform/x86/intel_pmc_ipc.c +++ b/drivers/platform/x86/intel_pmc_ipc.c @@ -96,18 +96,18 @@ static struct intel_pmc_ipc_dev { struct completion cmd_complete; /* The following PMC BARs share the same ACPI device with the IPC */ - void *acpi_io_base; + resource_size_t acpi_io_base; int acpi_io_size; struct platform_device *tco_dev; /* gcr */ - void *gcr_base; + resource_size_t gcr_base; int gcr_size; /* punit */ - void *punit_base; + resource_size_t punit_base; int punit_size; - void *punit_base2; + resource_size_t punit_base2; int punit_size2; struct platform_device *punit_dev; } ipcdev; @@ -210,10 +210,15 @@ static int intel_pmc_ipc_check_status(void) return ret; } -/* - * intel_pmc_ipc_simple_command - * @cmd: command - * @sub: sub type +/** + * intel_pmc_ipc_simple_command() - Simple IPC command + * @cmd: IPC command code. + * @sub: IPC command sub type. + * + * Send a simple IPC command to PMC when don't need to specify + * input/output data and source/dest pointers. + * + * Return: an IPC error code or 0 on success. */ int intel_pmc_ipc_simple_command(int cmd, int sub) { @@ -232,16 +237,20 @@ int intel_pmc_ipc_simple_command(int cmd, int sub) } EXPORT_SYMBOL_GPL(intel_pmc_ipc_simple_command); -/* - * intel_pmc_ipc_raw_cmd - * @cmd: command - * @sub: sub type - * @in: input data - * @inlen: input length in bytes - * @out: output data - * @outlen: output length in dwords - * @sptr: data writing to SPTR register - * @dptr: data writing to DPTR register +/** + * intel_pmc_ipc_raw_cmd() - IPC command with data and pointers + * @cmd: IPC command code. + * @sub: IPC command sub type. + * @in: input data of this IPC command. + * @inlen: input data length in bytes. + * @out: output data of this IPC command. + * @outlen: output data length in dwords. + * @sptr: data writing to SPTR register. + * @dptr: data writing to DPTR register. + * + * Send an IPC command to PMC with input/output data and source/dest pointers. + * + * Return: an IPC error code or 0 on success. */ int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen, u32 *out, u32 outlen, u32 dptr, u32 sptr) @@ -278,14 +287,18 @@ int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen, u32 *out, } EXPORT_SYMBOL_GPL(intel_pmc_ipc_raw_cmd); -/* - * intel_pmc_ipc_command - * @cmd: command - * @sub: sub type - * @in: input data - * @inlen: input length in bytes - * @out: output data - * @outlen: output length in dwords +/** + * intel_pmc_ipc_command() - IPC command with input/output data + * @cmd: IPC command code. + * @sub: IPC command sub type. + * @in: input data of this IPC command. + * @inlen: input data length in bytes. + * @out: output data of this IPC command. + * @outlen: output data length in dwords. + * + * Send an IPC command to PMC with input/output data. + * + * Return: an IPC error code or 0 on success. */ int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen, u32 *out, u32 outlen) @@ -480,11 +493,11 @@ static int ipc_create_punit_device(void) pdev->dev.parent = ipcdev.dev; res = punit_res; - res->start = (resource_size_t)ipcdev.punit_base; + res->start = ipcdev.punit_base; res->end = res->start + ipcdev.punit_size - 1; res = punit_res + PUNIT_RESOURCE_INTER; - res->start = (resource_size_t)ipcdev.punit_base2; + res->start = ipcdev.punit_base2; res->end = res->start + ipcdev.punit_size2 - 1; ret = platform_device_add_resources(pdev, punit_res, @@ -522,15 +535,15 @@ static int ipc_create_tco_device(void) pdev->dev.parent = ipcdev.dev; res = tco_res + TCO_RESOURCE_ACPI_IO; - res->start = (resource_size_t)ipcdev.acpi_io_base + TCO_BASE_OFFSET; + res->start = ipcdev.acpi_io_base + TCO_BASE_OFFSET; res->end = res->start + TCO_REGS_SIZE - 1; res = tco_res + TCO_RESOURCE_SMI_EN_IO; - res->start = (resource_size_t)ipcdev.acpi_io_base + SMI_EN_OFFSET; + res->start = ipcdev.acpi_io_base + SMI_EN_OFFSET; res->end = res->start + SMI_EN_SIZE - 1; res = tco_res + TCO_RESOURCE_GCR_MEM; - res->start = (resource_size_t)ipcdev.gcr_base; + res->start = ipcdev.gcr_base; res->end = res->start + ipcdev.gcr_size - 1; ret = platform_device_add_resources(pdev, tco_res, ARRAY_SIZE(tco_res)); @@ -589,7 +602,7 @@ static int ipc_plat_get_res(struct platform_device *pdev) return -ENXIO; } size = resource_size(res); - ipcdev.acpi_io_base = (void *)res->start; + ipcdev.acpi_io_base = res->start; ipcdev.acpi_io_size = size; dev_info(&pdev->dev, "io res: %llx %x\n", (long long)res->start, (int)resource_size(res)); @@ -601,7 +614,7 @@ static int ipc_plat_get_res(struct platform_device *pdev) return -ENXIO; } size = resource_size(res); - ipcdev.punit_base = (void *)res->start; + ipcdev.punit_base = res->start; ipcdev.punit_size = size; dev_info(&pdev->dev, "punit data res: %llx %x\n", (long long)res->start, (int)resource_size(res)); @@ -613,7 +626,7 @@ static int ipc_plat_get_res(struct platform_device *pdev) return -ENXIO; } size = resource_size(res); - ipcdev.punit_base2 = (void *)res->start; + ipcdev.punit_base2 = res->start; ipcdev.punit_size2 = size; dev_info(&pdev->dev, "punit interface res: %llx %x\n", (long long)res->start, (int)resource_size(res)); @@ -637,7 +650,7 @@ static int ipc_plat_get_res(struct platform_device *pdev) } ipcdev.ipc_base = addr; - ipcdev.gcr_base = (void *)(res->start + size); + ipcdev.gcr_base = res->start + size; ipcdev.gcr_size = PLAT_RESOURCE_GCR_SIZE; dev_info(&pdev->dev, "ipc res: %llx %x\n", (long long)res->start, (int)resource_size(res)); diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c index 001b199a8c33..187d1086d15c 100644 --- a/drivers/platform/x86/intel_scu_ipc.c +++ b/drivers/platform/x86/intel_scu_ipc.c @@ -216,13 +216,13 @@ static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id) int nc; u32 offset = 0; int err; - u8 cbuf[IPC_WWBUF_SIZE] = { }; + u8 cbuf[IPC_WWBUF_SIZE]; u32 *wbuf = (u32 *)&cbuf; - mutex_lock(&ipclock); - memset(cbuf, 0, sizeof(cbuf)); + mutex_lock(&ipclock); + if (ipcdev.pdev == NULL) { mutex_unlock(&ipclock); return -ENODEV; diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c index 515f33882ab8..49c1720df59a 100644 --- a/drivers/pnp/system.c +++ b/drivers/pnp/system.c @@ -7,7 +7,6 @@ * Bjorn Helgaas <bjorn.helgaas@hp.com> */ -#include <linux/acpi.h> #include <linux/pnp.h> #include <linux/device.h> #include <linux/init.h> @@ -23,41 +22,25 @@ static const struct pnp_device_id pnp_dev_table[] = { {"", 0} }; -#ifdef CONFIG_ACPI -static bool __reserve_range(u64 start, unsigned int length, bool io, char *desc) -{ - u8 space_id = io ? ACPI_ADR_SPACE_SYSTEM_IO : ACPI_ADR_SPACE_SYSTEM_MEMORY; - return !acpi_reserve_region(start, length, space_id, IORESOURCE_BUSY, desc); -} -#else -static bool __reserve_range(u64 start, unsigned int length, bool io, char *desc) -{ - struct resource *res; - - res = io ? request_region(start, length, desc) : - request_mem_region(start, length, desc); - if (res) { - res->flags &= ~IORESOURCE_BUSY; - return true; - } - return false; -} -#endif - static void reserve_range(struct pnp_dev *dev, struct resource *r, int port) { char *regionid; const char *pnpid = dev_name(&dev->dev); resource_size_t start = r->start, end = r->end; - bool reserved; + struct resource *res; regionid = kmalloc(16, GFP_KERNEL); if (!regionid) return; snprintf(regionid, 16, "pnp %s", pnpid); - reserved = __reserve_range(start, end - start + 1, !!port, regionid); - if (!reserved) + if (port) + res = request_region(start, end - start + 1, regionid); + else + res = request_mem_region(start, end - start + 1, regionid); + if (res) + res->flags &= ~IORESOURCE_BUSY; + else kfree(regionid); /* @@ -66,7 +49,7 @@ static void reserve_range(struct pnp_dev *dev, struct resource *r, int port) * have double reservations. */ dev_info(&dev->dev, "%pR %s reserved\n", r, - reserved ? "has been" : "could not be"); + res ? "has been" : "could not be"); } static void reserve_resources_of_dev(struct pnp_dev *dev) diff --git a/drivers/regulator/88pm800.c b/drivers/regulator/88pm800.c index 832932bdc977..7fd4f511d78f 100644 --- a/drivers/regulator/88pm800.c +++ b/drivers/regulator/88pm800.c @@ -130,7 +130,7 @@ struct pm800_regulators { .owner = THIS_MODULE, \ .n_voltages = ARRAY_SIZE(ldo_volt_table), \ .vsel_reg = PM800_##vreg##_VOUT, \ - .vsel_mask = 0x1f, \ + .vsel_mask = 0xf, \ .enable_reg = PM800_##ereg, \ .enable_mask = 1 << (ebit), \ .volt_table = ldo_volt_table, \ diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index c9f72019bd68..78387a6cbae5 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -109,6 +109,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, static struct regulator *create_regulator(struct regulator_dev *rdev, struct device *dev, const char *supply_name); +static void _regulator_put(struct regulator *regulator); static const char *rdev_get_name(struct regulator_dev *rdev) { @@ -1105,6 +1106,9 @@ static int set_supply(struct regulator_dev *rdev, rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); + if (!try_module_get(supply_rdev->owner)) + return -ENODEV; + rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); if (rdev->supply == NULL) { err = -ENOMEM; @@ -1381,9 +1385,13 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) } if (!r) { - dev_err(dev, "Failed to resolve %s-supply for %s\n", - rdev->supply_name, rdev->desc->name); - return -EPROBE_DEFER; + if (have_full_constraints()) { + r = dummy_regulator_rdev; + } else { + dev_err(dev, "Failed to resolve %s-supply for %s\n", + rdev->supply_name, rdev->desc->name); + return -EPROBE_DEFER; + } } /* Recursively resolve the supply of the supply */ @@ -1398,8 +1406,11 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) /* Cascade always-on state to supply */ if (_regulator_is_enabled(rdev)) { ret = regulator_enable(rdev->supply); - if (ret < 0) + if (ret < 0) { + if (rdev->supply) + _regulator_put(rdev->supply); return ret; + } } return 0; diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c index 6f2bdad8b4d8..e94ddcf97722 100644 --- a/drivers/regulator/max8973-regulator.c +++ b/drivers/regulator/max8973-regulator.c @@ -450,7 +450,7 @@ static struct max8973_regulator_platform_data *max8973_parse_dt( pdata->control_flags |= MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE; if (of_property_read_bool(np, "maxim,enable-bias-control")) - pdata->control_flags |= MAX8973_BIAS_ENABLE; + pdata->control_flags |= MAX8973_CONTROL_BIAS_ENABLE; return pdata; } diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 326ffb553371..72fc3c32db49 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -34,6 +34,8 @@ #include <linux/mfd/samsung/s2mps14.h> #include <linux/mfd/samsung/s2mpu02.h> +/* The highest number of possible regulators for supported devices. */ +#define S2MPS_REGULATOR_MAX S2MPS13_REGULATOR_MAX struct s2mps11_info { unsigned int rdev_num; int ramp_delay2; @@ -49,7 +51,7 @@ struct s2mps11_info { * One bit for each S2MPS13/S2MPS14/S2MPU02 regulator whether * the suspend mode was enabled. */ - unsigned long long s2mps14_suspend_state:50; + DECLARE_BITMAP(suspend_state, S2MPS_REGULATOR_MAX); /* Array of size rdev_num with GPIO-s for external sleep control */ int *ext_control_gpio; @@ -500,7 +502,7 @@ static int s2mps14_regulator_enable(struct regulator_dev *rdev) switch (s2mps11->dev_type) { case S2MPS13X: case S2MPS14X: - if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev))) + if (test_bit(rdev_get_id(rdev), s2mps11->suspend_state)) val = S2MPS14_ENABLE_SUSPEND; else if (gpio_is_valid(s2mps11->ext_control_gpio[rdev_get_id(rdev)])) val = S2MPS14_ENABLE_EXT_CONTROL; @@ -508,7 +510,7 @@ static int s2mps14_regulator_enable(struct regulator_dev *rdev) val = rdev->desc->enable_mask; break; case S2MPU02: - if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev))) + if (test_bit(rdev_get_id(rdev), s2mps11->suspend_state)) val = S2MPU02_ENABLE_SUSPEND; else val = rdev->desc->enable_mask; @@ -562,7 +564,7 @@ static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev) if (ret < 0) return ret; - s2mps11->s2mps14_suspend_state |= (1 << rdev_get_id(rdev)); + set_bit(rdev_get_id(rdev), s2mps11->suspend_state); /* * Don't enable suspend mode if regulator is already disabled because * this would effectively for a short time turn on the regulator after @@ -960,18 +962,22 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) case S2MPS11X: s2mps11->rdev_num = ARRAY_SIZE(s2mps11_regulators); regulators = s2mps11_regulators; + BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num); break; case S2MPS13X: s2mps11->rdev_num = ARRAY_SIZE(s2mps13_regulators); regulators = s2mps13_regulators; + BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num); break; case S2MPS14X: s2mps11->rdev_num = ARRAY_SIZE(s2mps14_regulators); regulators = s2mps14_regulators; + BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num); break; case S2MPU02: s2mps11->rdev_num = ARRAY_SIZE(s2mpu02_regulators); regulators = s2mpu02_regulators; + BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num); break; default: dev_err(&pdev->dev, "Invalid device type: %u\n", diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c index 4b62d1a875e4..2b08cac62f07 100644 --- a/drivers/rtc/rtc-armada38x.c +++ b/drivers/rtc/rtc-armada38x.c @@ -88,7 +88,7 @@ static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct armada38x_rtc *rtc = dev_get_drvdata(dev); int ret = 0; - unsigned long time, flags; + unsigned long time; ret = rtc_tm_to_time(tm, &time); diff --git a/drivers/rtc/rtc-mt6397.c b/drivers/rtc/rtc-mt6397.c index c0090b698ff3..eab230be5a54 100644 --- a/drivers/rtc/rtc-mt6397.c +++ b/drivers/rtc/rtc-mt6397.c @@ -343,6 +343,8 @@ static int mtk_rtc_probe(struct platform_device *pdev) goto out_dispose_irq; } + device_init_wakeup(&pdev->dev, 1); + rtc->rtc_dev = rtc_device_register("mt6397-rtc", &pdev->dev, &mtk_rtc_ops, THIS_MODULE); if (IS_ERR(rtc->rtc_dev)) { @@ -351,8 +353,6 @@ static int mtk_rtc_probe(struct platform_device *pdev) goto out_free_irq; } - device_init_wakeup(&pdev->dev, 1); - return 0; out_free_irq: diff --git a/drivers/s390/Makefile b/drivers/s390/Makefile index 95bccfd3f169..e5225ad9c5b1 100644 --- a/drivers/s390/Makefile +++ b/drivers/s390/Makefile @@ -2,7 +2,7 @@ # Makefile for the S/390 specific device drivers # -obj-y += cio/ block/ char/ crypto/ net/ scsi/ kvm/ +obj-y += cio/ block/ char/ crypto/ net/ scsi/ virtio/ drivers-y += drivers/s390/built-in.o diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 1aec8ff0b587..f73d2f579a7e 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -1863,6 +1863,33 @@ static void __dasd_device_check_expire(struct dasd_device *device) } /* + * return 1 when device is not eligible for IO + */ +static int __dasd_device_is_unusable(struct dasd_device *device, + struct dasd_ccw_req *cqr) +{ + int mask = ~(DASD_STOPPED_DC_WAIT | DASD_UNRESUMED_PM); + + if (test_bit(DASD_FLAG_OFFLINE, &device->flags)) { + /* dasd is being set offline. */ + return 1; + } + if (device->stopped) { + if (device->stopped & mask) { + /* stopped and CQR will not change that. */ + return 1; + } + if (!test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags)) { + /* CQR is not able to change device to + * operational. */ + return 1; + } + /* CQR required to get device operational. */ + } + return 0; +} + +/* * Take a look at the first request on the ccw queue and check * if it needs to be started. */ @@ -1876,13 +1903,8 @@ static void __dasd_device_start_head(struct dasd_device *device) cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, devlist); if (cqr->status != DASD_CQR_QUEUED) return; - /* when device is stopped, return request to previous layer - * exception: only the disconnect or unresumed bits are set and the - * cqr is a path verification request - */ - if (device->stopped && - !(!(device->stopped & ~(DASD_STOPPED_DC_WAIT | DASD_UNRESUMED_PM)) - && test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags))) { + /* if device is not usable return request to upper layer */ + if (__dasd_device_is_unusable(device, cqr)) { cqr->intrc = -EAGAIN; cqr->status = DASD_CQR_CLEARED; dasd_schedule_device_bh(device); diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index a2597e683e79..ee3a6faae22a 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c @@ -699,7 +699,8 @@ struct dasd_device *dasd_alias_get_start_dev(struct dasd_device *base_device) struct dasd_device, alias_list); spin_unlock_irqrestore(&lcu->lock, flags); alias_priv = (struct dasd_eckd_private *) alias_device->private; - if ((alias_priv->count < private->count) && !alias_device->stopped) + if ((alias_priv->count < private->count) && !alias_device->stopped && + !test_bit(DASD_FLAG_OFFLINE, &alias_device->flags)) return alias_device; else return NULL; diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index aeed7969fd79..7bc6df3100ef 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -7,6 +7,7 @@ #define KMSG_COMPONENT "sclp_early" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt +#include <linux/errno.h> #include <asm/ctl_reg.h> #include <asm/sclp.h> #include <asm/ipl.h> diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 08f1830cbfc4..01bf1f5cf2e9 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -54,6 +54,10 @@ MODULE_DESCRIPTION("Cryptographic Coprocessor interface, " \ "Copyright IBM Corp. 2001, 2012"); MODULE_LICENSE("GPL"); +static int zcrypt_hwrng_seed = 1; +module_param_named(hwrng_seed, zcrypt_hwrng_seed, int, S_IRUSR|S_IRGRP); +MODULE_PARM_DESC(hwrng_seed, "Turn on/off hwrng auto seed, default is 1 (on)."); + static DEFINE_SPINLOCK(zcrypt_device_lock); static LIST_HEAD(zcrypt_device_list); static int zcrypt_device_count = 0; @@ -1373,6 +1377,7 @@ static int zcrypt_rng_data_read(struct hwrng *rng, u32 *data) static struct hwrng zcrypt_rng_dev = { .name = "zcrypt", .data_read = zcrypt_rng_data_read, + .quality = 990, }; static int zcrypt_rng_device_add(void) @@ -1387,6 +1392,8 @@ static int zcrypt_rng_device_add(void) goto out; } zcrypt_rng_buffer_index = 0; + if (!zcrypt_hwrng_seed) + zcrypt_rng_dev.quality = 0; rc = hwrng_register(&zcrypt_rng_dev); if (rc) goto out_free; diff --git a/drivers/s390/kvm/Makefile b/drivers/s390/virtio/Makefile index 241891a57caf..241891a57caf 100644 --- a/drivers/s390/kvm/Makefile +++ b/drivers/s390/virtio/Makefile diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/virtio/kvm_virtio.c index 53fb975c404b..53fb975c404b 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/virtio/kvm_virtio.c diff --git a/drivers/s390/kvm/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c index f8d8fdb26b72..f8d8fdb26b72 100644 --- a/drivers/s390/kvm/virtio_ccw.c +++ b/drivers/s390/virtio/virtio_ccw.c diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 882744852aac..a9aa38903efe 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -599,9 +599,10 @@ static void ipr_trc_hook(struct ipr_cmnd *ipr_cmd, { struct ipr_trace_entry *trace_entry; struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; + unsigned int trace_index; - trace_entry = &ioa_cfg->trace[atomic_add_return - (1, &ioa_cfg->trace_index)%IPR_NUM_TRACE_ENTRIES]; + trace_index = atomic_add_return(1, &ioa_cfg->trace_index) & IPR_TRACE_INDEX_MASK; + trace_entry = &ioa_cfg->trace[trace_index]; trace_entry->time = jiffies; trace_entry->op_code = ipr_cmd->ioarcb.cmd_pkt.cdb[0]; trace_entry->type = type; @@ -1051,10 +1052,15 @@ static void ipr_send_blocking_cmd(struct ipr_cmnd *ipr_cmd, static int ipr_get_hrrq_index(struct ipr_ioa_cfg *ioa_cfg) { + unsigned int hrrq; + if (ioa_cfg->hrrq_num == 1) - return 0; - else - return (atomic_add_return(1, &ioa_cfg->hrrq_index) % (ioa_cfg->hrrq_num - 1)) + 1; + hrrq = 0; + else { + hrrq = atomic_add_return(1, &ioa_cfg->hrrq_index); + hrrq = (hrrq % (ioa_cfg->hrrq_num - 1)) + 1; + } + return hrrq; } /** @@ -6263,21 +6269,23 @@ static void ipr_scsi_done(struct ipr_cmnd *ipr_cmd) struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd; u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); - unsigned long hrrq_flags; + unsigned long lock_flags; scsi_set_resid(scsi_cmd, be32_to_cpu(ipr_cmd->s.ioasa.hdr.residual_data_len)); if (likely(IPR_IOASC_SENSE_KEY(ioasc) == 0)) { scsi_dma_unmap(scsi_cmd); - spin_lock_irqsave(ipr_cmd->hrrq->lock, hrrq_flags); + spin_lock_irqsave(ipr_cmd->hrrq->lock, lock_flags); list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); scsi_cmd->scsi_done(scsi_cmd); - spin_unlock_irqrestore(ipr_cmd->hrrq->lock, hrrq_flags); + spin_unlock_irqrestore(ipr_cmd->hrrq->lock, lock_flags); } else { - spin_lock_irqsave(ipr_cmd->hrrq->lock, hrrq_flags); + spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); + spin_lock(&ipr_cmd->hrrq->_lock); ipr_erp_start(ioa_cfg, ipr_cmd); - spin_unlock_irqrestore(ipr_cmd->hrrq->lock, hrrq_flags); + spin_unlock(&ipr_cmd->hrrq->_lock); + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); } } diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 73790a1d0969..6b97ee45c7b4 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -1486,6 +1486,7 @@ struct ipr_ioa_cfg { #define IPR_NUM_TRACE_INDEX_BITS 8 #define IPR_NUM_TRACE_ENTRIES (1 << IPR_NUM_TRACE_INDEX_BITS) +#define IPR_TRACE_INDEX_MASK (IPR_NUM_TRACE_ENTRIES - 1) #define IPR_TRACE_SIZE (sizeof(struct ipr_trace_entry) * IPR_NUM_TRACE_ENTRIES) char trace_start[8]; #define IPR_TRACE_START_LABEL "trace" diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 82b92c414a9c..437254e1c4de 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -738,7 +738,7 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj, ql_log(ql_log_info, vha, 0x706f, "Issuing MPI reset.\n"); - if (IS_QLA83XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { uint32_t idc_control; qla83xx_idc_lock(vha, 0); diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 0e6ee3ca30e6..8b011aef12bd 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -67,10 +67,10 @@ * | | | 0xd031-0xd0ff | * | | | 0xd101-0xd1fe | * | | | 0xd214-0xd2fe | - * | Target Mode | 0xe079 | | - * | Target Mode Management | 0xf072 | 0xf002 | + * | Target Mode | 0xe080 | | + * | Target Mode Management | 0xf096 | 0xf002 | * | | | 0xf046-0xf049 | - * | Target Mode Task Management | 0x1000b | | + * | Target Mode Task Management | 0x1000d | | * ---------------------------------------------------------------------- */ diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index e86201d3b8c6..9ad819edcd67 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -274,6 +274,7 @@ #define RESPONSE_ENTRY_CNT_FX00 256 /* Number of response entries.*/ struct req_que; +struct qla_tgt_sess; /* * (sd.h is not exported, hence local inclusion) @@ -2026,6 +2027,7 @@ typedef struct fc_port { uint16_t port_id; unsigned long retry_delay_timestamp; + struct qla_tgt_sess *tgt_session; } fc_port_t; #include "qla_mr.h" @@ -3154,13 +3156,13 @@ struct qla_hw_data { /* Bit 21 of fw_attributes decides the MCTP capabilities */ #define IS_MCTP_CAPABLE(ha) (IS_QLA2031(ha) && \ ((ha)->fw_attributes_ext[0] & BIT_0)) -#define IS_PI_UNINIT_CAPABLE(ha) (IS_QLA83XX(ha)) -#define IS_PI_IPGUARD_CAPABLE(ha) (IS_QLA83XX(ha)) +#define IS_PI_UNINIT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) +#define IS_PI_IPGUARD_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) #define IS_PI_DIFB_DIX0_CAPABLE(ha) (0) -#define IS_PI_SPLIT_DET_CAPABLE_HBA(ha) (IS_QLA83XX(ha)) +#define IS_PI_SPLIT_DET_CAPABLE_HBA(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) #define IS_PI_SPLIT_DET_CAPABLE(ha) (IS_PI_SPLIT_DET_CAPABLE_HBA(ha) && \ (((ha)->fw_attributes_h << 16 | (ha)->fw_attributes) & BIT_22)) -#define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha)) +#define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) #define IS_TGT_MODE_CAPABLE(ha) (ha->tgt.atio_q_length) #define IS_SHADOW_REG_CAPABLE(ha) (IS_QLA27XX(ha)) #define IS_DPORT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) @@ -3579,6 +3581,16 @@ typedef struct scsi_qla_host { uint16_t fcoe_fcf_idx; uint8_t fcoe_vn_port_mac[6]; + /* list of commands waiting on workqueue */ + struct list_head qla_cmd_list; + struct list_head qla_sess_op_cmd_list; + spinlock_t cmd_list_lock; + + /* Counter to detect races between ELS and RSCN events */ + atomic_t generation_tick; + /* Time when global fcport update has been scheduled */ + int total_fcport_update_gen; + uint32_t vp_abort_cnt; struct fc_vport *fc_vport; /* holds fc_vport * for each vport */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 664013115c9d..11f2f3279eab 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -115,6 +115,8 @@ qla2x00_async_iocb_timeout(void *data) QLA_LOGIO_LOGIN_RETRIED : 0; qla2x00_post_async_login_done_work(fcport->vha, fcport, lio->u.logio.data); + } else if (sp->type == SRB_LOGOUT_CMD) { + qlt_logo_completion_handler(fcport, QLA_FUNCTION_TIMEOUT); } } @@ -497,7 +499,10 @@ void qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport, uint16_t *data) { - qla2x00_mark_device_lost(vha, fcport, 1, 0); + /* Don't re-login in target mode */ + if (!fcport->tgt_session) + qla2x00_mark_device_lost(vha, fcport, 1, 0); + qlt_logo_completion_handler(fcport, data[0]); return; } @@ -1538,7 +1543,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) mem_size = (ha->fw_memory_size - 0x11000 + 1) * sizeof(uint16_t); } else if (IS_FWI2_CAPABLE(ha)) { - if (IS_QLA83XX(ha)) + if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) fixed_size = offsetof(struct qla83xx_fw_dump, ext_mem); else if (IS_QLA81XX(ha)) fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem); @@ -1550,7 +1555,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) mem_size = (ha->fw_memory_size - 0x100000 + 1) * sizeof(uint32_t); if (ha->mqenable) { - if (!IS_QLA83XX(ha)) + if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) mq_size = sizeof(struct qla2xxx_mq_chain); /* * Allocate maximum buffer size for all queues. @@ -2922,21 +2927,14 @@ qla2x00_rport_del(void *data) { fc_port_t *fcport = data; struct fc_rport *rport; - scsi_qla_host_t *vha = fcport->vha; unsigned long flags; spin_lock_irqsave(fcport->vha->host->host_lock, flags); rport = fcport->drport ? fcport->drport: fcport->rport; fcport->drport = NULL; spin_unlock_irqrestore(fcport->vha->host->host_lock, flags); - if (rport) { + if (rport) fc_remote_port_delete(rport); - /* - * Release the target mode FC NEXUS in qla_target.c code - * if target mod is enabled. - */ - qlt_fc_port_deleted(vha, fcport); - } } /** @@ -3303,6 +3301,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport) * Create target mode FC NEXUS in qla_target.c if target mode is * enabled.. */ + qlt_fc_port_added(vha, fcport); spin_lock_irqsave(fcport->vha->host->host_lock, flags); @@ -3341,8 +3340,7 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) if (IS_QLAFX00(vha->hw)) { qla2x00_set_fcport_state(fcport, FCS_ONLINE); - qla2x00_reg_remote_port(vha, fcport); - return; + goto reg_port; } fcport->login_retry = 0; fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT); @@ -3350,7 +3348,16 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) qla2x00_set_fcport_state(fcport, FCS_ONLINE); qla2x00_iidma_fcport(vha, fcport); qla24xx_update_fcport_fcp_prio(vha, fcport); - qla2x00_reg_remote_port(vha, fcport); + +reg_port: + if (qla_ini_mode_enabled(vha)) + qla2x00_reg_remote_port(vha, fcport); + else { + /* + * Create target mode FC NEXUS in qla_target.c + */ + qlt_fc_port_added(vha, fcport); + } } /* @@ -3375,6 +3382,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) LIST_HEAD(new_fcports); struct qla_hw_data *ha = vha->hw; struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); + int discovery_gen; /* If FL port exists, then SNS is present */ if (IS_FWI2_CAPABLE(ha)) @@ -3445,6 +3453,14 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) fcport->scan_state = QLA_FCPORT_SCAN; } + /* Mark the time right before querying FW for connected ports. + * This process is long, asynchronous and by the time it's done, + * collected information might not be accurate anymore. E.g. + * disconnected port might have re-connected and a brand new + * session has been created. In this case session's generation + * will be newer than discovery_gen. */ + qlt_do_generation_tick(vha, &discovery_gen); + rval = qla2x00_find_all_fabric_devs(vha, &new_fcports); if (rval != QLA_SUCCESS) break; @@ -3460,20 +3476,44 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) continue; - if (fcport->scan_state == QLA_FCPORT_SCAN && - atomic_read(&fcport->state) == FCS_ONLINE) { - qla2x00_mark_device_lost(vha, fcport, - ql2xplogiabsentdevice, 0); - if (fcport->loop_id != FC_NO_LOOP_ID && - (fcport->flags & FCF_FCP2_DEVICE) == 0 && - fcport->port_type != FCT_INITIATOR && - fcport->port_type != FCT_BROADCAST) { - ha->isp_ops->fabric_logout(vha, - fcport->loop_id, - fcport->d_id.b.domain, - fcport->d_id.b.area, - fcport->d_id.b.al_pa); - qla2x00_clear_loop_id(fcport); + if (fcport->scan_state == QLA_FCPORT_SCAN) { + if (qla_ini_mode_enabled(base_vha) && + atomic_read(&fcport->state) == FCS_ONLINE) { + qla2x00_mark_device_lost(vha, fcport, + ql2xplogiabsentdevice, 0); + if (fcport->loop_id != FC_NO_LOOP_ID && + (fcport->flags & FCF_FCP2_DEVICE) == 0 && + fcport->port_type != FCT_INITIATOR && + fcport->port_type != FCT_BROADCAST) { + ha->isp_ops->fabric_logout(vha, + fcport->loop_id, + fcport->d_id.b.domain, + fcport->d_id.b.area, + fcport->d_id.b.al_pa); + qla2x00_clear_loop_id(fcport); + } + } else if (!qla_ini_mode_enabled(base_vha)) { + /* + * In target mode, explicitly kill + * sessions and log out of devices + * that are gone, so that we don't + * end up with an initiator using the + * wrong ACL (if the fabric recycles + * an FC address and we have a stale + * session around) and so that we don't + * report initiators that are no longer + * on the fabric. + */ + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf077, + "port gone, logging out/killing session: " + "%8phC state 0x%x flags 0x%x fc4_type 0x%x " + "scan_state %d\n", + fcport->port_name, + atomic_read(&fcport->state), + fcport->flags, fcport->fc4_type, + fcport->scan_state); + qlt_fc_port_deleted(vha, fcport, + discovery_gen); } } } @@ -3494,6 +3534,28 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) (fcport->flags & FCF_LOGIN_NEEDED) == 0) continue; + /* + * If we're not an initiator, skip looking for devices + * and logging in. There's no reason for us to do it, + * and it seems to actively cause problems in target + * mode if we race with the initiator logging into us + * (we might get the "port ID used" status back from + * our login command and log out the initiator, which + * seems to cause havoc). + */ + if (!qla_ini_mode_enabled(base_vha)) { + if (fcport->scan_state == QLA_FCPORT_FOUND) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf078, + "port %8phC state 0x%x flags 0x%x fc4_type 0x%x " + "scan_state %d (initiator mode disabled; skipping " + "login)\n", fcport->port_name, + atomic_read(&fcport->state), + fcport->flags, fcport->fc4_type, + fcport->scan_state); + } + continue; + } + if (fcport->loop_id == FC_NO_LOOP_ID) { fcport->loop_id = next_loopid; rval = qla2x00_find_new_loop_id( @@ -3520,16 +3582,38 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) break; - /* Find a new loop ID to use. */ - fcport->loop_id = next_loopid; - rval = qla2x00_find_new_loop_id(base_vha, fcport); - if (rval != QLA_SUCCESS) { - /* Ran out of IDs to use */ - break; - } + /* + * If we're not an initiator, skip looking for devices + * and logging in. There's no reason for us to do it, + * and it seems to actively cause problems in target + * mode if we race with the initiator logging into us + * (we might get the "port ID used" status back from + * our login command and log out the initiator, which + * seems to cause havoc). + */ + if (qla_ini_mode_enabled(base_vha)) { + /* Find a new loop ID to use. */ + fcport->loop_id = next_loopid; + rval = qla2x00_find_new_loop_id(base_vha, + fcport); + if (rval != QLA_SUCCESS) { + /* Ran out of IDs to use */ + break; + } - /* Login and update database */ - qla2x00_fabric_dev_login(vha, fcport, &next_loopid); + /* Login and update database */ + qla2x00_fabric_dev_login(vha, fcport, + &next_loopid); + } else { + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf079, + "new port %8phC state 0x%x flags 0x%x fc4_type " + "0x%x scan_state %d (initiator mode disabled; " + "skipping login)\n", + fcport->port_name, + atomic_read(&fcport->state), + fcport->flags, fcport->fc4_type, + fcport->scan_state); + } list_move_tail(&fcport->list, &vha->vp_fcports); } @@ -3725,11 +3809,12 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, fcport->fp_speed = new_fcport->fp_speed; /* - * If address the same and state FCS_ONLINE, nothing - * changed. + * If address the same and state FCS_ONLINE + * (or in target mode), nothing changed. */ if (fcport->d_id.b24 == new_fcport->d_id.b24 && - atomic_read(&fcport->state) == FCS_ONLINE) { + (atomic_read(&fcport->state) == FCS_ONLINE || + !qla_ini_mode_enabled(base_vha))) { break; } @@ -3749,6 +3834,22 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, * Log it out if still logged in and mark it for * relogin later. */ + if (!qla_ini_mode_enabled(base_vha)) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf080, + "port changed FC ID, %8phC" + " old %x:%x:%x (loop_id 0x%04x)-> new %x:%x:%x\n", + fcport->port_name, + fcport->d_id.b.domain, + fcport->d_id.b.area, + fcport->d_id.b.al_pa, + fcport->loop_id, + new_fcport->d_id.b.domain, + new_fcport->d_id.b.area, + new_fcport->d_id.b.al_pa); + fcport->d_id.b24 = new_fcport->d_id.b24; + break; + } + fcport->d_id.b24 = new_fcport->d_id.b24; fcport->flags |= FCF_LOGIN_NEEDED; if (fcport->loop_id != FC_NO_LOOP_ID && @@ -3768,6 +3869,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, if (found) continue; /* If device was not in our fcports list, then add it. */ + new_fcport->scan_state = QLA_FCPORT_FOUND; list_add_tail(&new_fcport->list, new_fcports); /* Allocate a new replacement fcport. */ @@ -4188,6 +4290,14 @@ qla2x00_update_fcports(scsi_qla_host_t *base_vha) atomic_read(&fcport->state) != FCS_UNCONFIGURED) { spin_unlock_irqrestore(&ha->vport_slock, flags); qla2x00_rport_del(fcport); + + /* + * Release the target mode FC NEXUS in + * qla_target.c, if target mod is enabled. + */ + qlt_fc_port_deleted(vha, fcport, + base_vha->total_fcport_update_gen); + spin_lock_irqsave(&ha->vport_slock, flags); } } diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 36fbd4c7af8f..6f02b26a35cf 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -1943,6 +1943,9 @@ qla24xx_logout_iocb(srb_t *sp, struct logio_entry_24xx *logio) logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; logio->control_flags = cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO); + if (!sp->fcport->tgt_session || + !sp->fcport->tgt_session->keep_nport_handle) + logio->control_flags |= cpu_to_le16(LCF_FREE_NPORT); logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); logio->port_id[0] = sp->fcport->d_id.b.al_pa; logio->port_id[1] = sp->fcport->d_id.b.area; diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 02b1c1c5355b..b2f713ad9034 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -2415,7 +2415,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha, uint16_t *cur_xchg_cnt, *orig_iocb_cnt = mcp->mb[10]; if (vha->hw->flags.npiv_supported && max_npiv_vports) *max_npiv_vports = mcp->mb[11]; - if ((IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw)) && max_fcfs) + if ((IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw) || + IS_QLA27XX(vha->hw)) && max_fcfs) *max_fcfs = mcp->mb[12]; } @@ -3898,7 +3899,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp) spin_lock_irqsave(&ha->hardware_lock, flags); if (!(rsp->options & BIT_0)) { WRT_REG_DWORD(rsp->rsp_q_out, 0); - if (!IS_QLA83XX(ha)) + if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) WRT_REG_DWORD(rsp->rsp_q_in, 0); } @@ -5345,7 +5346,7 @@ qla83xx_restart_nic_firmware(scsi_qla_host_t *vha) mbx_cmd_t *mcp = &mc; struct qla_hw_data *ha = vha->hw; - if (!IS_QLA83XX(ha)) + if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) return QLA_FUNCTION_FAILED; ql_dbg(ql_dbg_mbx, vha, 0x1143, "Entered %s.\n", __func__); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index a28815b8276f..8a5cac8448c7 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2504,6 +2504,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->mbx_count = MAILBOX_REGISTER_COUNT; req_length = REQUEST_ENTRY_CNT_24XX; rsp_length = RESPONSE_ENTRY_CNT_2300; + ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX; ha->max_loop_id = SNS_LAST_LOOP_ID_2300; ha->init_cb_size = sizeof(struct mid_init_cb_81xx); ha->gid_list_info_size = 8; @@ -3229,11 +3230,15 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport, spin_lock_irqsave(vha->host->host_lock, flags); fcport->drport = rport; spin_unlock_irqrestore(vha->host->host_lock, flags); + qlt_do_generation_tick(vha, &base_vha->total_fcport_update_gen); set_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags); qla2xxx_wake_dpc(base_vha); } else { - fc_remote_port_delete(rport); - qlt_fc_port_deleted(vha, fcport); + int now; + if (rport) + fc_remote_port_delete(rport); + qlt_do_generation_tick(vha, &now); + qlt_fc_port_deleted(vha, fcport, now); } } @@ -3763,8 +3768,11 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, INIT_LIST_HEAD(&vha->vp_fcports); INIT_LIST_HEAD(&vha->work_list); INIT_LIST_HEAD(&vha->list); + INIT_LIST_HEAD(&vha->qla_cmd_list); + INIT_LIST_HEAD(&vha->qla_sess_op_cmd_list); spin_lock_init(&vha->work_lock); + spin_lock_init(&vha->cmd_list_lock); sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no); ql_dbg(ql_dbg_init, vha, 0x0041, diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 028e8c8a7de9..2feb5f38edcd 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -1697,7 +1697,7 @@ qla83xx_select_led_port(struct qla_hw_data *ha) { uint32_t led_select_value = 0; - if (!IS_QLA83XX(ha)) + if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) goto out; if (ha->port_no == 0) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index b749026aa592..58651ecbd88c 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -113,6 +113,11 @@ static void qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha, static void qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, struct atio_from_isp *atio, uint16_t status, int qfull); static void qlt_disable_vha(struct scsi_qla_host *vha); +static void qlt_clear_tgt_db(struct qla_tgt *tgt); +static void qlt_send_notify_ack(struct scsi_qla_host *vha, + struct imm_ntfy_from_isp *ntfy, + uint32_t add_flags, uint16_t resp_code, int resp_code_valid, + uint16_t srr_flags, uint16_t srr_reject_code, uint8_t srr_explan); /* * Global Variables */ @@ -122,6 +127,16 @@ static struct workqueue_struct *qla_tgt_wq; static DEFINE_MUTEX(qla_tgt_mutex); static LIST_HEAD(qla_tgt_glist); +/* This API intentionally takes dest as a parameter, rather than returning + * int value to avoid caller forgetting to issue wmb() after the store */ +void qlt_do_generation_tick(struct scsi_qla_host *vha, int *dest) +{ + scsi_qla_host_t *base_vha = pci_get_drvdata(vha->hw->pdev); + *dest = atomic_inc_return(&base_vha->generation_tick); + /* memory barrier */ + wmb(); +} + /* ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list) */ static struct qla_tgt_sess *qlt_find_sess_by_port_name( struct qla_tgt *tgt, @@ -381,14 +396,73 @@ static void qlt_free_session_done(struct work_struct *work) struct qla_tgt *tgt = sess->tgt; struct scsi_qla_host *vha = sess->vha; struct qla_hw_data *ha = vha->hw; + unsigned long flags; + bool logout_started = false; + fc_port_t fcport; + + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf084, + "%s: se_sess %p / sess %p from port %8phC loop_id %#04x" + " s_id %02x:%02x:%02x logout %d keep %d plogi %d\n", + __func__, sess->se_sess, sess, sess->port_name, sess->loop_id, + sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa, + sess->logout_on_delete, sess->keep_nport_handle, + sess->plogi_ack_needed); BUG_ON(!tgt); + + if (sess->logout_on_delete) { + int rc; + + memset(&fcport, 0, sizeof(fcport)); + fcport.loop_id = sess->loop_id; + fcport.d_id = sess->s_id; + memcpy(fcport.port_name, sess->port_name, WWN_SIZE); + fcport.vha = vha; + fcport.tgt_session = sess; + + rc = qla2x00_post_async_logout_work(vha, &fcport, NULL); + if (rc != QLA_SUCCESS) + ql_log(ql_log_warn, vha, 0xf085, + "Schedule logo failed sess %p rc %d\n", + sess, rc); + else + logout_started = true; + } + /* * Release the target session for FC Nexus from fabric module code. */ if (sess->se_sess != NULL) ha->tgt.tgt_ops->free_session(sess); + if (logout_started) { + bool traced = false; + + while (!ACCESS_ONCE(sess->logout_completed)) { + if (!traced) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf086, + "%s: waiting for sess %p logout\n", + __func__, sess); + traced = true; + } + msleep(100); + } + + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf087, + "%s: sess %p logout completed\n", + __func__, sess); + } + + spin_lock_irqsave(&ha->hardware_lock, flags); + + if (sess->plogi_ack_needed) + qlt_send_notify_ack(vha, &sess->tm_iocb, + 0, 0, 0, 0, 0, 0); + + list_del(&sess->sess_list_entry); + + spin_unlock_irqrestore(&ha->hardware_lock, flags); + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf001, "Unregistration of sess %p finished\n", sess); @@ -409,9 +483,9 @@ void qlt_unreg_sess(struct qla_tgt_sess *sess) vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess); - list_del(&sess->sess_list_entry); - if (sess->deleted) - list_del(&sess->del_list_entry); + if (!list_empty(&sess->del_list_entry)) + list_del_init(&sess->del_list_entry); + sess->deleted = QLA_SESS_DELETION_IN_PROGRESS; INIT_WORK(&sess->free_work, qlt_free_session_done); schedule_work(&sess->free_work); @@ -431,10 +505,10 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd) loop_id = le16_to_cpu(n->u.isp24.nport_handle); if (loop_id == 0xFFFF) { -#if 0 /* FIXME: Re-enable Global event handling.. */ /* Global event */ - atomic_inc(&ha->tgt.qla_tgt->tgt_global_resets_count); - qlt_clear_tgt_db(ha->tgt.qla_tgt); + atomic_inc(&vha->vha_tgt.qla_tgt->tgt_global_resets_count); + qlt_clear_tgt_db(vha->vha_tgt.qla_tgt); +#if 0 /* FIXME: do we need to choose a session here? */ if (!list_empty(&ha->tgt.qla_tgt->sess_list)) { sess = list_entry(ha->tgt.qla_tgt->sess_list.next, typeof(*sess), sess_list_entry); @@ -489,27 +563,38 @@ static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess, struct qla_tgt *tgt = sess->tgt; uint32_t dev_loss_tmo = tgt->ha->port_down_retry_count + 5; - if (sess->deleted) - return; + if (sess->deleted) { + /* Upgrade to unconditional deletion in case it was temporary */ + if (immediate && sess->deleted == QLA_SESS_DELETION_PENDING) + list_del(&sess->del_list_entry); + else + return; + } ql_dbg(ql_dbg_tgt, sess->vha, 0xe001, "Scheduling sess %p for deletion\n", sess); - list_add_tail(&sess->del_list_entry, &tgt->del_sess_list); - sess->deleted = 1; - if (immediate) + if (immediate) { dev_loss_tmo = 0; + sess->deleted = QLA_SESS_DELETION_IN_PROGRESS; + list_add(&sess->del_list_entry, &tgt->del_sess_list); + } else { + sess->deleted = QLA_SESS_DELETION_PENDING; + list_add_tail(&sess->del_list_entry, &tgt->del_sess_list); + } sess->expires = jiffies + dev_loss_tmo * HZ; ql_dbg(ql_dbg_tgt, sess->vha, 0xe048, - "qla_target(%d): session for port %8phC (loop ID %d) scheduled for " - "deletion in %u secs (expires: %lu) immed: %d\n", - sess->vha->vp_idx, sess->port_name, sess->loop_id, dev_loss_tmo, - sess->expires, immediate); + "qla_target(%d): session for port %8phC (loop ID %d s_id %02x:%02x:%02x)" + " scheduled for deletion in %u secs (expires: %lu) immed: %d, logout: %d, gen: %#x\n", + sess->vha->vp_idx, sess->port_name, sess->loop_id, + sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa, + dev_loss_tmo, sess->expires, immediate, sess->logout_on_delete, + sess->generation); if (immediate) - schedule_delayed_work(&tgt->sess_del_work, 0); + mod_delayed_work(system_wq, &tgt->sess_del_work, 0); else schedule_delayed_work(&tgt->sess_del_work, sess->expires - jiffies); @@ -578,9 +663,9 @@ out_free_id_list: /* ha->hardware_lock supposed to be held on entry */ static void qlt_undelete_sess(struct qla_tgt_sess *sess) { - BUG_ON(!sess->deleted); + BUG_ON(sess->deleted != QLA_SESS_DELETION_PENDING); - list_del(&sess->del_list_entry); + list_del_init(&sess->del_list_entry); sess->deleted = 0; } @@ -599,7 +684,9 @@ static void qlt_del_sess_work_fn(struct delayed_work *work) del_list_entry); elapsed = jiffies; if (time_after_eq(elapsed, sess->expires)) { - qlt_undelete_sess(sess); + /* No turning back */ + list_del_init(&sess->del_list_entry); + sess->deleted = QLA_SESS_DELETION_IN_PROGRESS; ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004, "Timeout: sess %p about to be deleted\n", @@ -643,6 +730,13 @@ static struct qla_tgt_sess *qlt_create_sess( fcport->d_id.b.al_pa, fcport->d_id.b.area, fcport->loop_id); + /* Cannot undelete at this point */ + if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { + spin_unlock_irqrestore(&ha->hardware_lock, + flags); + return NULL; + } + if (sess->deleted) qlt_undelete_sess(sess); @@ -652,6 +746,9 @@ static struct qla_tgt_sess *qlt_create_sess( if (sess->local && !local) sess->local = 0; + + qlt_do_generation_tick(vha, &sess->generation); + spin_unlock_irqrestore(&ha->hardware_lock, flags); return sess; @@ -673,6 +770,14 @@ static struct qla_tgt_sess *qlt_create_sess( sess->s_id = fcport->d_id; sess->loop_id = fcport->loop_id; sess->local = local; + INIT_LIST_HEAD(&sess->del_list_entry); + + /* Under normal circumstances we want to logout from firmware when + * session eventually ends and release corresponding nport handle. + * In the exception cases (e.g. when new PLOGI is waiting) corresponding + * code will adjust these flags as necessary. */ + sess->logout_on_delete = 1; + sess->keep_nport_handle = 0; ql_dbg(ql_dbg_tgt_mgt, vha, 0xf006, "Adding sess %p to tgt %p via ->check_initiator_node_acl()\n", @@ -705,6 +810,7 @@ static struct qla_tgt_sess *qlt_create_sess( spin_lock_irqsave(&ha->hardware_lock, flags); list_add_tail(&sess->sess_list_entry, &vha->vha_tgt.qla_tgt->sess_list); vha->vha_tgt.qla_tgt->sess_count++; + qlt_do_generation_tick(vha, &sess->generation); spin_unlock_irqrestore(&ha->hardware_lock, flags); ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04b, @@ -718,7 +824,7 @@ static struct qla_tgt_sess *qlt_create_sess( } /* - * Called from drivers/scsi/qla2xxx/qla_init.c:qla2x00_reg_remote_port() + * Called from qla2x00_reg_remote_port() */ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) { @@ -750,6 +856,10 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) mutex_unlock(&vha->vha_tgt.tgt_mutex); spin_lock_irqsave(&ha->hardware_lock, flags); + } else if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { + /* Point of no return */ + spin_unlock_irqrestore(&ha->hardware_lock, flags); + return; } else { kref_get(&sess->se_sess->sess_kref); @@ -780,27 +890,36 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) spin_unlock_irqrestore(&ha->hardware_lock, flags); } -void qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport) +/* + * max_gen - specifies maximum session generation + * at which this deletion requestion is still valid + */ +void +qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport, int max_gen) { - struct qla_hw_data *ha = vha->hw; struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; struct qla_tgt_sess *sess; - unsigned long flags; if (!vha->hw->tgt.tgt_ops) return; - if (!tgt || (fcport->port_type != FCT_INITIATOR)) + if (!tgt) return; - spin_lock_irqsave(&ha->hardware_lock, flags); if (tgt->tgt_stop) { - spin_unlock_irqrestore(&ha->hardware_lock, flags); return; } sess = qlt_find_sess_by_port_name(tgt, fcport->port_name); if (!sess) { - spin_unlock_irqrestore(&ha->hardware_lock, flags); + return; + } + + if (max_gen - sess->generation < 0) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf092, + "Ignoring stale deletion request for se_sess %p / sess %p" + " for port %8phC, req_gen %d, sess_gen %d\n", + sess->se_sess, sess, sess->port_name, max_gen, + sess->generation); return; } @@ -808,7 +927,6 @@ void qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport) sess->local = 1; qlt_schedule_sess_for_deletion(sess, false); - spin_unlock_irqrestore(&ha->hardware_lock, flags); } static inline int test_tgt_sess_count(struct qla_tgt *tgt) @@ -1175,6 +1293,70 @@ static void qlt_24xx_retry_term_exchange(struct scsi_qla_host *vha, FCP_TMF_CMPL, true); } +static int abort_cmd_for_tag(struct scsi_qla_host *vha, uint32_t tag) +{ + struct qla_tgt_sess_op *op; + struct qla_tgt_cmd *cmd; + + spin_lock(&vha->cmd_list_lock); + + list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) { + if (tag == op->atio.u.isp24.exchange_addr) { + op->aborted = true; + spin_unlock(&vha->cmd_list_lock); + return 1; + } + } + + list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) { + if (tag == cmd->atio.u.isp24.exchange_addr) { + cmd->state = QLA_TGT_STATE_ABORTED; + spin_unlock(&vha->cmd_list_lock); + return 1; + } + } + + spin_unlock(&vha->cmd_list_lock); + return 0; +} + +/* drop cmds for the given lun + * XXX only looks for cmds on the port through which lun reset was recieved + * XXX does not go through the list of other port (which may have cmds + * for the same lun) + */ +static void abort_cmds_for_lun(struct scsi_qla_host *vha, + uint32_t lun, uint8_t *s_id) +{ + struct qla_tgt_sess_op *op; + struct qla_tgt_cmd *cmd; + uint32_t key; + + key = sid_to_key(s_id); + spin_lock(&vha->cmd_list_lock); + list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) { + uint32_t op_key; + uint32_t op_lun; + + op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id); + op_lun = scsilun_to_int( + (struct scsi_lun *)&op->atio.u.isp24.fcp_cmnd.lun); + if (op_key == key && op_lun == lun) + op->aborted = true; + } + list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) { + uint32_t cmd_key; + uint32_t cmd_lun; + + cmd_key = sid_to_key(cmd->atio.u.isp24.fcp_hdr.s_id); + cmd_lun = scsilun_to_int( + (struct scsi_lun *)&cmd->atio.u.isp24.fcp_cmnd.lun); + if (cmd_key == key && cmd_lun == lun) + cmd->state = QLA_TGT_STATE_ABORTED; + } + spin_unlock(&vha->cmd_list_lock); +} + /* ha->hardware_lock supposed to be held on entry */ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha, struct abts_recv_from_24xx *abts, struct qla_tgt_sess *sess) @@ -1199,8 +1381,19 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha, } spin_unlock(&se_sess->sess_cmd_lock); - if (!found_lun) - return -ENOENT; + /* cmd not in LIO lists, look in qla list */ + if (!found_lun) { + if (abort_cmd_for_tag(vha, abts->exchange_addr_to_abort)) { + /* send TASK_ABORT response immediately */ + qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_CMPL, false); + return 0; + } else { + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf081, + "unable to find cmd in driver or LIO for tag 0x%x\n", + abts->exchange_addr_to_abort); + return -ENOENT; + } + } ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00f, "qla_target(%d): task abort (tag=%d)\n", @@ -1284,6 +1477,11 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha, return; } + if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { + qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false); + return; + } + rc = __qlt_24xx_handle_abts(vha, abts, sess); if (rc != 0) { ql_dbg(ql_dbg_tgt_mgt, vha, 0xf054, @@ -1726,20 +1924,6 @@ static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd, struct qla_hw_data *ha = vha->hw; struct se_cmd *se_cmd = &cmd->se_cmd; - if (unlikely(cmd->aborted)) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014, - "qla_target(%d): terminating exchange for aborted cmd=%p (se_cmd=%p, tag=%lld)", - vha->vp_idx, cmd, se_cmd, se_cmd->tag); - - cmd->state = QLA_TGT_STATE_ABORTED; - cmd->cmd_flags |= BIT_6; - - qlt_send_term_exchange(vha, cmd, &cmd->atio, 0); - - /* !! At this point cmd could be already freed !! */ - return QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED; - } - prm->cmd = cmd; prm->tgt = tgt; prm->rq_result = scsi_status; @@ -2301,6 +2485,19 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, unsigned long flags = 0; int res; + spin_lock_irqsave(&ha->hardware_lock, flags); + if (cmd->sess && cmd->sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { + cmd->state = QLA_TGT_STATE_PROCESSED; + if (cmd->sess->logout_completed) + /* no need to terminate. FW already freed exchange. */ + qlt_abort_cmd_on_host_reset(cmd->vha, cmd); + else + qlt_send_term_exchange(vha, cmd, &cmd->atio, 1); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + return 0; + } + spin_unlock_irqrestore(&ha->hardware_lock, flags); + memset(&prm, 0, sizeof(prm)); qlt_check_srr_debug(cmd, &xmit_type); @@ -2313,9 +2510,6 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, res = qlt_pre_xmit_response(cmd, &prm, xmit_type, scsi_status, &full_req_cnt); if (unlikely(res != 0)) { - if (res == QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED) - return 0; - return res; } @@ -2345,9 +2539,10 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, res = qlt_build_ctio_crc2_pkt(&prm, vha); else res = qlt_24xx_build_ctio_pkt(&prm, vha); - if (unlikely(res != 0)) + if (unlikely(res != 0)) { + vha->req->cnt += full_req_cnt; goto out_unmap_unlock; - + } pkt = (struct ctio7_to_24xx *)prm.pkt; @@ -2461,7 +2656,8 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) spin_lock_irqsave(&ha->hardware_lock, flags); - if (qla2x00_reset_active(vha) || cmd->reset_count != ha->chip_reset) { + if (qla2x00_reset_active(vha) || (cmd->reset_count != ha->chip_reset) || + (cmd->sess && cmd->sess->deleted == QLA_SESS_DELETION_IN_PROGRESS)) { /* * Either a chip reset is active or this request was from * previous life, just abort the processing. @@ -2485,8 +2681,11 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) else res = qlt_24xx_build_ctio_pkt(&prm, vha); - if (unlikely(res != 0)) + if (unlikely(res != 0)) { + vha->req->cnt += prm.req_cnt; goto out_unlock_free_unmap; + } + pkt = (struct ctio7_to_24xx *)prm.pkt; pkt->u.status0.flags |= __constant_cpu_to_le16(CTIO7_FLAGS_DATA_OUT | CTIO7_FLAGS_STATUS_MODE_0); @@ -2651,6 +2850,89 @@ out: /* If hardware_lock held on entry, might drop it, then reaquire */ /* This function sends the appropriate CTIO to ISP 2xxx or 24xx */ +static int __qlt_send_term_imm_notif(struct scsi_qla_host *vha, + struct imm_ntfy_from_isp *ntfy) +{ + struct nack_to_isp *nack; + struct qla_hw_data *ha = vha->hw; + request_t *pkt; + int ret = 0; + + ql_dbg(ql_dbg_tgt_tmr, vha, 0xe01c, + "Sending TERM ELS CTIO (ha=%p)\n", ha); + + pkt = (request_t *)qla2x00_alloc_iocbs_ready(vha, NULL); + if (pkt == NULL) { + ql_dbg(ql_dbg_tgt, vha, 0xe080, + "qla_target(%d): %s failed: unable to allocate " + "request packet\n", vha->vp_idx, __func__); + return -ENOMEM; + } + + pkt->entry_type = NOTIFY_ACK_TYPE; + pkt->entry_count = 1; + pkt->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK; + + nack = (struct nack_to_isp *)pkt; + nack->ox_id = ntfy->ox_id; + + nack->u.isp24.nport_handle = ntfy->u.isp24.nport_handle; + if (le16_to_cpu(ntfy->u.isp24.status) == IMM_NTFY_ELS) { + nack->u.isp24.flags = ntfy->u.isp24.flags & + __constant_cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB); + } + + /* terminate */ + nack->u.isp24.flags |= + __constant_cpu_to_le16(NOTIFY_ACK_FLAGS_TERMINATE); + + nack->u.isp24.srr_rx_id = ntfy->u.isp24.srr_rx_id; + nack->u.isp24.status = ntfy->u.isp24.status; + nack->u.isp24.status_subcode = ntfy->u.isp24.status_subcode; + nack->u.isp24.fw_handle = ntfy->u.isp24.fw_handle; + nack->u.isp24.exchange_address = ntfy->u.isp24.exchange_address; + nack->u.isp24.srr_rel_offs = ntfy->u.isp24.srr_rel_offs; + nack->u.isp24.srr_ui = ntfy->u.isp24.srr_ui; + nack->u.isp24.vp_index = ntfy->u.isp24.vp_index; + + qla2x00_start_iocbs(vha, vha->req); + return ret; +} + +static void qlt_send_term_imm_notif(struct scsi_qla_host *vha, + struct imm_ntfy_from_isp *imm, int ha_locked) +{ + unsigned long flags = 0; + int rc; + + if (qlt_issue_marker(vha, ha_locked) < 0) + return; + + if (ha_locked) { + rc = __qlt_send_term_imm_notif(vha, imm); + +#if 0 /* Todo */ + if (rc == -ENOMEM) + qlt_alloc_qfull_cmd(vha, imm, 0, 0); +#endif + goto done; + } + + spin_lock_irqsave(&vha->hw->hardware_lock, flags); + rc = __qlt_send_term_imm_notif(vha, imm); + +#if 0 /* Todo */ + if (rc == -ENOMEM) + qlt_alloc_qfull_cmd(vha, imm, 0, 0); +#endif + +done: + if (!ha_locked) + spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); +} + +/* If hardware_lock held on entry, might drop it, then reaquire */ +/* This function sends the appropriate CTIO to ISP 2xxx or 24xx */ static int __qlt_send_term_exchange(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd, struct atio_from_isp *atio) @@ -2715,7 +2997,7 @@ static int __qlt_send_term_exchange(struct scsi_qla_host *vha, static void qlt_send_term_exchange(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked) { - unsigned long flags; + unsigned long flags = 0; int rc; if (qlt_issue_marker(vha, ha_locked) < 0) @@ -2731,17 +3013,18 @@ static void qlt_send_term_exchange(struct scsi_qla_host *vha, rc = __qlt_send_term_exchange(vha, cmd, atio); if (rc == -ENOMEM) qlt_alloc_qfull_cmd(vha, atio, 0, 0); - spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); done: if (cmd && ((cmd->state != QLA_TGT_STATE_ABORTED) || !cmd->cmd_sent_to_fw)) { - if (!ha_locked && !in_interrupt()) - msleep(250); /* just in case */ - - qlt_unmap_sg(vha, cmd); + if (cmd->sg_mapped) + qlt_unmap_sg(vha, cmd); vha->hw->tgt.tgt_ops->free_cmd(cmd); } + + if (!ha_locked) + spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); + return; } @@ -2792,6 +3075,24 @@ static void qlt_chk_exch_leak_thresh_hold(struct scsi_qla_host *vha) } +void qlt_abort_cmd(struct qla_tgt_cmd *cmd) +{ + struct qla_tgt *tgt = cmd->tgt; + struct scsi_qla_host *vha = tgt->vha; + struct se_cmd *se_cmd = &cmd->se_cmd; + + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014, + "qla_target(%d): terminating exchange for aborted cmd=%p " + "(se_cmd=%p, tag=%llu)", vha->vp_idx, cmd, &cmd->se_cmd, + se_cmd->tag); + + cmd->state = QLA_TGT_STATE_ABORTED; + cmd->cmd_flags |= BIT_6; + + qlt_send_term_exchange(vha, cmd, &cmd->atio, 0); +} +EXPORT_SYMBOL(qlt_abort_cmd); + void qlt_free_cmd(struct qla_tgt_cmd *cmd) { struct qla_tgt_sess *sess = cmd->sess; @@ -3015,7 +3316,7 @@ qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd) dump_stack(); } - cmd->cmd_flags |= BIT_12; + cmd->cmd_flags |= BIT_17; ha->tgt.tgt_ops->free_cmd(cmd); } @@ -3177,7 +3478,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle, skip_term: if (cmd->state == QLA_TGT_STATE_PROCESSED) { - ; + cmd->cmd_flags |= BIT_12; } else if (cmd->state == QLA_TGT_STATE_NEED_DATA) { int rx_status = 0; @@ -3191,9 +3492,11 @@ skip_term: ha->tgt.tgt_ops->handle_data(cmd); return; } else if (cmd->state == QLA_TGT_STATE_ABORTED) { + cmd->cmd_flags |= BIT_18; ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01e, "Aborted command %p (tag %lld) finished\n", cmd, se_cmd->tag); } else { + cmd->cmd_flags |= BIT_19; ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05c, "qla_target(%d): A command in state (%d) should " "not return a CTIO complete\n", vha->vp_idx, cmd->state); @@ -3205,7 +3508,6 @@ skip_term: dump_stack(); } - ha->tgt.tgt_ops->free_cmd(cmd); } @@ -3263,6 +3565,13 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd) if (tgt->tgt_stop) goto out_term; + if (cmd->state == QLA_TGT_STATE_ABORTED) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf082, + "cmd with tag %u is aborted\n", + cmd->atio.u.isp24.exchange_addr); + goto out_term; + } + cdb = &atio->u.isp24.fcp_cmnd.cdb[0]; cmd->se_cmd.tag = atio->u.isp24.exchange_addr; cmd->unpacked_lun = scsilun_to_int( @@ -3316,6 +3625,12 @@ out_term: static void qlt_do_work(struct work_struct *work) { struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); + scsi_qla_host_t *vha = cmd->vha; + unsigned long flags; + + spin_lock_irqsave(&vha->cmd_list_lock, flags); + list_del(&cmd->cmd_list); + spin_unlock_irqrestore(&vha->cmd_list_lock, flags); __qlt_do_work(cmd); } @@ -3345,6 +3660,11 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha, cmd->loop_id = sess->loop_id; cmd->conf_compl_supported = sess->conf_compl_supported; + cmd->cmd_flags = 0; + cmd->jiffies_at_alloc = get_jiffies_64(); + + cmd->reset_count = vha->hw->chip_reset; + return cmd; } @@ -3362,14 +3682,25 @@ static void qlt_create_sess_from_atio(struct work_struct *work) unsigned long flags; uint8_t *s_id = op->atio.u.isp24.fcp_hdr.s_id; + spin_lock_irqsave(&vha->cmd_list_lock, flags); + list_del(&op->cmd_list); + spin_unlock_irqrestore(&vha->cmd_list_lock, flags); + + if (op->aborted) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf083, + "sess_op with tag %u is aborted\n", + op->atio.u.isp24.exchange_addr); + goto out_term; + } + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf022, - "qla_target(%d): Unable to find wwn login" - " (s_id %x:%x:%x), trying to create it manually\n", - vha->vp_idx, s_id[0], s_id[1], s_id[2]); + "qla_target(%d): Unable to find wwn login" + " (s_id %x:%x:%x), trying to create it manually\n", + vha->vp_idx, s_id[0], s_id[1], s_id[2]); if (op->atio.u.raw.entry_count > 1) { ql_dbg(ql_dbg_tgt_mgt, vha, 0xf023, - "Dropping multy entry atio %p\n", &op->atio); + "Dropping multy entry atio %p\n", &op->atio); goto out_term; } @@ -3434,10 +3765,25 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, memcpy(&op->atio, atio, sizeof(*atio)); op->vha = vha; + + spin_lock(&vha->cmd_list_lock); + list_add_tail(&op->cmd_list, &vha->qla_sess_op_cmd_list); + spin_unlock(&vha->cmd_list_lock); + INIT_WORK(&op->work, qlt_create_sess_from_atio); queue_work(qla_tgt_wq, &op->work); return 0; } + + /* Another WWN used to have our s_id. Our PLOGI scheduled its + * session deletion, but it's still in sess_del_work wq */ + if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { + ql_dbg(ql_dbg_io, vha, 0x3061, + "New command while old session %p is being deleted\n", + sess); + return -EFAULT; + } + /* * Do kref_get() before returning + dropping qla_hw_data->hardware_lock. */ @@ -3451,13 +3797,13 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, return -ENOMEM; } - cmd->cmd_flags = 0; - cmd->jiffies_at_alloc = get_jiffies_64(); - - cmd->reset_count = vha->hw->chip_reset; - cmd->cmd_in_wq = 1; cmd->cmd_flags |= BIT_0; + + spin_lock(&vha->cmd_list_lock); + list_add_tail(&cmd->cmd_list, &vha->qla_cmd_list); + spin_unlock(&vha->cmd_list_lock); + INIT_WORK(&cmd->work, qlt_do_work); queue_work(qla_tgt_wq, &cmd->work); return 0; @@ -3471,6 +3817,7 @@ static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun, struct scsi_qla_host *vha = sess->vha; struct qla_hw_data *ha = vha->hw; struct qla_tgt_mgmt_cmd *mcmd; + struct atio_from_isp *a = (struct atio_from_isp *)iocb; int res; uint8_t tmr_func; @@ -3511,6 +3858,7 @@ static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun, ql_dbg(ql_dbg_tgt_tmr, vha, 0x10002, "qla_target(%d): LUN_RESET received\n", sess->vha->vp_idx); tmr_func = TMR_LUN_RESET; + abort_cmds_for_lun(vha, lun, a->u.isp24.fcp_hdr.s_id); break; case QLA_TGT_CLEAR_TS: @@ -3599,6 +3947,9 @@ static int qlt_handle_task_mgmt(struct scsi_qla_host *vha, void *iocb) sizeof(struct atio_from_isp)); } + if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) + return -EFAULT; + return qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0); } @@ -3664,22 +4015,280 @@ static int qlt_abort_task(struct scsi_qla_host *vha, return __qlt_abort_task(vha, iocb, sess); } +void qlt_logo_completion_handler(fc_port_t *fcport, int rc) +{ + if (fcport->tgt_session) { + if (rc != MBS_COMMAND_COMPLETE) { + ql_dbg(ql_dbg_tgt_mgt, fcport->vha, 0xf093, + "%s: se_sess %p / sess %p from" + " port %8phC loop_id %#04x s_id %02x:%02x:%02x" + " LOGO failed: %#x\n", + __func__, + fcport->tgt_session->se_sess, + fcport->tgt_session, + fcport->port_name, fcport->loop_id, + fcport->d_id.b.domain, fcport->d_id.b.area, + fcport->d_id.b.al_pa, rc); + } + + fcport->tgt_session->logout_completed = 1; + } +} + +static void qlt_swap_imm_ntfy_iocb(struct imm_ntfy_from_isp *a, + struct imm_ntfy_from_isp *b) +{ + struct imm_ntfy_from_isp tmp; + memcpy(&tmp, a, sizeof(struct imm_ntfy_from_isp)); + memcpy(a, b, sizeof(struct imm_ntfy_from_isp)); + memcpy(b, &tmp, sizeof(struct imm_ntfy_from_isp)); +} + +/* +* ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list) +* +* Schedules sessions with matching port_id/loop_id but different wwn for +* deletion. Returns existing session with matching wwn if present. +* Null otherwise. +*/ +static struct qla_tgt_sess * +qlt_find_sess_invalidate_other(struct qla_tgt *tgt, uint64_t wwn, + port_id_t port_id, uint16_t loop_id) +{ + struct qla_tgt_sess *sess = NULL, *other_sess; + uint64_t other_wwn; + + list_for_each_entry(other_sess, &tgt->sess_list, sess_list_entry) { + + other_wwn = wwn_to_u64(other_sess->port_name); + + if (wwn == other_wwn) { + WARN_ON(sess); + sess = other_sess; + continue; + } + + /* find other sess with nport_id collision */ + if (port_id.b24 == other_sess->s_id.b24) { + if (loop_id != other_sess->loop_id) { + ql_dbg(ql_dbg_tgt_tmr, tgt->vha, 0x1000c, + "Invalidating sess %p loop_id %d wwn %llx.\n", + other_sess, other_sess->loop_id, other_wwn); + + /* + * logout_on_delete is set by default, but another + * session that has the same s_id/loop_id combo + * might have cleared it when requested this session + * deletion, so don't touch it + */ + qlt_schedule_sess_for_deletion(other_sess, true); + } else { + /* + * Another wwn used to have our s_id/loop_id + * combo - kill the session, but don't log out + */ + sess->logout_on_delete = 0; + qlt_schedule_sess_for_deletion(other_sess, + true); + } + continue; + } + + /* find other sess with nport handle collision */ + if (loop_id == other_sess->loop_id) { + ql_dbg(ql_dbg_tgt_tmr, tgt->vha, 0x1000d, + "Invalidating sess %p loop_id %d wwn %llx.\n", + other_sess, other_sess->loop_id, other_wwn); + + /* Same loop_id but different s_id + * Ok to kill and logout */ + qlt_schedule_sess_for_deletion(other_sess, true); + } + } + + return sess; +} + +/* Abort any commands for this s_id waiting on qla_tgt_wq workqueue */ +static int abort_cmds_for_s_id(struct scsi_qla_host *vha, port_id_t *s_id) +{ + struct qla_tgt_sess_op *op; + struct qla_tgt_cmd *cmd; + uint32_t key; + int count = 0; + + key = (((u32)s_id->b.domain << 16) | + ((u32)s_id->b.area << 8) | + ((u32)s_id->b.al_pa)); + + spin_lock(&vha->cmd_list_lock); + list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) { + uint32_t op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id); + if (op_key == key) { + op->aborted = true; + count++; + } + } + list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) { + uint32_t cmd_key = sid_to_key(cmd->atio.u.isp24.fcp_hdr.s_id); + if (cmd_key == key) { + cmd->state = QLA_TGT_STATE_ABORTED; + count++; + } + } + spin_unlock(&vha->cmd_list_lock); + + return count; +} + /* * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire */ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, struct imm_ntfy_from_isp *iocb) { + struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; + struct qla_hw_data *ha = vha->hw; + struct qla_tgt_sess *sess = NULL; + uint64_t wwn; + port_id_t port_id; + uint16_t loop_id; + uint16_t wd3_lo; int res = 0; + wwn = wwn_to_u64(iocb->u.isp24.port_name); + + port_id.b.domain = iocb->u.isp24.port_id[2]; + port_id.b.area = iocb->u.isp24.port_id[1]; + port_id.b.al_pa = iocb->u.isp24.port_id[0]; + port_id.b.rsvd_1 = 0; + + loop_id = le16_to_cpu(iocb->u.isp24.nport_handle); + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf026, "qla_target(%d): Port ID: 0x%3phC ELS opcode: 0x%02x\n", vha->vp_idx, iocb->u.isp24.port_id, iocb->u.isp24.status_subcode); + /* res = 1 means ack at the end of thread + * res = 0 means ack async/later. + */ switch (iocb->u.isp24.status_subcode) { case ELS_PLOGI: - case ELS_FLOGI: + + /* Mark all stale commands in qla_tgt_wq for deletion */ + abort_cmds_for_s_id(vha, &port_id); + + if (wwn) + sess = qlt_find_sess_invalidate_other(tgt, wwn, + port_id, loop_id); + + if (!sess || IS_SW_RESV_ADDR(sess->s_id)) { + res = 1; + break; + } + + if (sess->plogi_ack_needed) { + /* + * Initiator sent another PLOGI before last PLOGI could + * finish. Swap plogi iocbs and terminate old one + * without acking, new one will get acked when session + * deletion completes. + */ + ql_log(ql_log_warn, sess->vha, 0xf094, + "sess %p received double plogi.\n", sess); + + qlt_swap_imm_ntfy_iocb(iocb, &sess->tm_iocb); + + qlt_send_term_imm_notif(vha, iocb, 1); + + res = 0; + break; + } + + res = 0; + + /* + * Save immediate Notif IOCB for Ack when sess is done + * and being deleted. + */ + memcpy(&sess->tm_iocb, iocb, sizeof(sess->tm_iocb)); + sess->plogi_ack_needed = 1; + + /* + * Under normal circumstances we want to release nport handle + * during LOGO process to avoid nport handle leaks inside FW. + * The exception is when LOGO is done while another PLOGI with + * the same nport handle is waiting as might be the case here. + * Note: there is always a possibily of a race where session + * deletion has already started for other reasons (e.g. ACL + * removal) and now PLOGI arrives: + * 1. if PLOGI arrived in FW after nport handle has been freed, + * FW must have assigned this PLOGI a new/same handle and we + * can proceed ACK'ing it as usual when session deletion + * completes. + * 2. if PLOGI arrived in FW before LOGO with LCF_FREE_NPORT + * bit reached it, the handle has now been released. We'll + * get an error when we ACK this PLOGI. Nothing will be sent + * back to initiator. Initiator should eventually retry + * PLOGI and situation will correct itself. + */ + sess->keep_nport_handle = ((sess->loop_id == loop_id) && + (sess->s_id.b24 == port_id.b24)); + qlt_schedule_sess_for_deletion(sess, true); + break; + case ELS_PRLI: + wd3_lo = le16_to_cpu(iocb->u.isp24.u.prli.wd3_lo); + + if (wwn) + sess = qlt_find_sess_invalidate_other(tgt, wwn, port_id, + loop_id); + + if (sess != NULL) { + if (sess->deleted) { + /* + * Impatient initiator sent PRLI before last + * PLOGI could finish. Will force him to re-try, + * while last one finishes. + */ + ql_log(ql_log_warn, sess->vha, 0xf095, + "sess %p PRLI received, before plogi ack.\n", + sess); + qlt_send_term_imm_notif(vha, iocb, 1); + res = 0; + break; + } + + /* + * This shouldn't happen under normal circumstances, + * since we have deleted the old session during PLOGI + */ + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf096, + "PRLI (loop_id %#04x) for existing sess %p (loop_id %#04x)\n", + sess->loop_id, sess, iocb->u.isp24.nport_handle); + + sess->local = 0; + sess->loop_id = loop_id; + sess->s_id = port_id; + + if (wd3_lo & BIT_7) + sess->conf_compl_supported = 1; + + } + res = 1; /* send notify ack */ + + /* Make session global (not used in fabric mode) */ + if (ha->current_topology != ISP_CFG_F) { + set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); + set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); + qla2xxx_wake_dpc(vha); + } else { + /* todo: else - create sess here. */ + res = 1; /* send notify ack */ + } + + break; + case ELS_LOGO: case ELS_PRLO: res = qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS_SESS); @@ -3697,6 +4306,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, break; } + case ELS_FLOGI: /* should never happen */ default: ql_dbg(ql_dbg_tgt_mgt, vha, 0xf061, "qla_target(%d): Unsupported ELS command %x " @@ -5012,6 +5622,11 @@ static void qlt_abort_work(struct qla_tgt *tgt, if (!sess) goto out_term; } else { + if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { + sess = NULL; + goto out_term; + } + kref_get(&sess->se_sess->sess_kref); } @@ -5066,6 +5681,11 @@ static void qlt_tmr_work(struct qla_tgt *tgt, if (!sess) goto out_term; } else { + if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { + sess = NULL; + goto out_term; + } + kref_get(&sess->se_sess->sess_kref); } @@ -5552,6 +6172,7 @@ qlt_24xx_process_atio_queue(struct scsi_qla_host *vha) /* Adjust ring index */ WRT_REG_DWORD(ISP_ATIO_Q_OUT(vha), ha->tgt.atio_ring_index); + RD_REG_DWORD_RELAXED(ISP_ATIO_Q_OUT(vha)); } void @@ -5793,7 +6414,7 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha) if (!QLA_TGT_MODE_ENABLED()) return; - if (ha->mqenable || IS_QLA83XX(ha)) { + if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) { ISP_ATIO_Q_IN(base_vha) = &ha->mqiobase->isp25mq.atio_q_in; ISP_ATIO_Q_OUT(base_vha) = &ha->mqiobase->isp25mq.atio_q_out; } else { diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 985d76dd706b..bca584ae45b7 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -167,7 +167,24 @@ struct imm_ntfy_from_isp { uint32_t srr_rel_offs; uint16_t srr_ui; uint16_t srr_ox_id; - uint8_t reserved_4[19]; + union { + struct { + uint8_t node_name[8]; + } plogi; /* PLOGI/ADISC/PDISC */ + struct { + /* PRLI word 3 bit 0-15 */ + uint16_t wd3_lo; + uint8_t resv0[6]; + } prli; + struct { + uint8_t port_id[3]; + uint8_t resv1; + uint16_t nport_handle; + uint16_t resv2; + } req_els; + } u; + uint8_t port_name[8]; + uint8_t resv3[3]; uint8_t vp_index; uint32_t reserved_5; uint8_t port_id[3]; @@ -234,6 +251,7 @@ struct nack_to_isp { uint8_t reserved[2]; uint16_t ox_id; } __packed; +#define NOTIFY_ACK_FLAGS_TERMINATE BIT_3 #define NOTIFY_ACK_SRR_FLAGS_ACCEPT 0 #define NOTIFY_ACK_SRR_FLAGS_REJECT 1 @@ -790,13 +808,6 @@ int qla2x00_wait_for_hba_online(struct scsi_qla_host *); #define FC_TM_REJECT 4 #define FC_TM_FAILED 5 -/* - * Error code of qlt_pre_xmit_response() meaning that cmd's exchange was - * terminated, so no more actions is needed and success should be returned - * to target. - */ -#define QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED 0x1717 - #if (BITS_PER_LONG > 32) || defined(CONFIG_HIGHMEM64G) #define pci_dma_lo32(a) (a & 0xffffffff) #define pci_dma_hi32(a) ((((a) >> 16)>>16) & 0xffffffff) @@ -874,6 +885,15 @@ struct qla_tgt_sess_op { struct scsi_qla_host *vha; struct atio_from_isp atio; struct work_struct work; + struct list_head cmd_list; + bool aborted; +}; + +enum qla_sess_deletion { + QLA_SESS_DELETION_NONE = 0, + QLA_SESS_DELETION_PENDING = 1, /* hopefully we can get rid of + * this one */ + QLA_SESS_DELETION_IN_PROGRESS = 2, }; /* @@ -884,8 +904,15 @@ struct qla_tgt_sess { port_id_t s_id; unsigned int conf_compl_supported:1; - unsigned int deleted:1; + unsigned int deleted:2; unsigned int local:1; + unsigned int logout_on_delete:1; + unsigned int plogi_ack_needed:1; + unsigned int keep_nport_handle:1; + + unsigned char logout_completed; + + int generation; struct se_session *se_sess; struct scsi_qla_host *vha; @@ -897,6 +924,10 @@ struct qla_tgt_sess { uint8_t port_name[WWN_SIZE]; struct work_struct free_work; + + union { + struct imm_ntfy_from_isp tm_iocb; + }; }; struct qla_tgt_cmd { @@ -912,7 +943,6 @@ struct qla_tgt_cmd { unsigned int conf_compl_supported:1; unsigned int sg_mapped:1; unsigned int free_sg:1; - unsigned int aborted:1; /* Needed in case of SRR */ unsigned int write_data_transferred:1; unsigned int ctx_dsd_alloced:1; unsigned int q_full:1; @@ -961,6 +991,9 @@ struct qla_tgt_cmd { * BIT_14 - Back end data received/sent. * BIT_15 - SRR prepare ctio * BIT_16 - complete free + * BIT_17 - flush - qlt_abort_cmd_on_host_reset + * BIT_18 - completion w/abort status + * BIT_19 - completion w/unknown status */ uint32_t cmd_flags; }; @@ -1026,6 +1059,10 @@ struct qla_tgt_srr_ctio { struct qla_tgt_cmd *cmd; }; +/* Check for Switch reserved address */ +#define IS_SW_RESV_ADDR(_s_id) \ + ((_s_id.b.domain == 0xff) && (_s_id.b.area == 0xfc)) + #define QLA_TGT_XMIT_DATA 1 #define QLA_TGT_XMIT_STATUS 2 #define QLA_TGT_XMIT_ALL (QLA_TGT_XMIT_STATUS|QLA_TGT_XMIT_DATA) @@ -1043,7 +1080,7 @@ extern int qlt_lport_register(void *, u64, u64, u64, extern void qlt_lport_deregister(struct scsi_qla_host *); extern void qlt_unreg_sess(struct qla_tgt_sess *); extern void qlt_fc_port_added(struct scsi_qla_host *, fc_port_t *); -extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *); +extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *, int); extern int __init qlt_init(void); extern void qlt_exit(void); extern void qlt_update_vp_map(struct scsi_qla_host *, int); @@ -1073,12 +1110,23 @@ static inline void qla_reverse_ini_mode(struct scsi_qla_host *ha) ha->host->active_mode |= MODE_INITIATOR; } +static inline uint32_t sid_to_key(const uint8_t *s_id) +{ + uint32_t key; + + key = (((unsigned long)s_id[0] << 16) | + ((unsigned long)s_id[1] << 8) | + (unsigned long)s_id[2]); + return key; +} + /* * Exported symbols from qla_target.c LLD logic used by qla2xxx code.. */ extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, response_t *); extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *); extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t); +extern void qlt_abort_cmd(struct qla_tgt_cmd *); extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *); extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *); extern void qlt_free_cmd(struct qla_tgt_cmd *cmd); @@ -1109,5 +1157,7 @@ extern void qlt_stop_phase2(struct qla_tgt *); extern irqreturn_t qla83xx_msix_atio_q(int, void *); extern void qlt_83xx_iospace_config(struct qla_hw_data *); extern int qlt_free_qfull_cmds(struct scsi_qla_host *); +extern void qlt_logo_completion_handler(fc_port_t *, int); +extern void qlt_do_generation_tick(struct scsi_qla_host *, int *); #endif /* __QLA_TARGET_H */ diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index d9a8c6084346..9224a06646e6 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -374,7 +374,7 @@ static int tcm_qla2xxx_write_pending(struct se_cmd *se_cmd) { struct qla_tgt_cmd *cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd); - + cmd->cmd_flags |= BIT_3; cmd->bufflen = se_cmd->data_length; cmd->dma_data_direction = target_reverse_dma_direction(se_cmd); @@ -405,7 +405,7 @@ static int tcm_qla2xxx_write_pending_status(struct se_cmd *se_cmd) se_cmd->t_state == TRANSPORT_COMPLETE_QF_WP) { spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); wait_for_completion_timeout(&se_cmd->t_transport_stop_comp, - 3000); + 3 * HZ); return 0; } spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); @@ -541,12 +541,10 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd) cmd->cmd_flags |= BIT_4; cmd->bufflen = se_cmd->data_length; cmd->dma_data_direction = target_reverse_dma_direction(se_cmd); - cmd->aborted = (se_cmd->transport_state & CMD_T_ABORTED); cmd->sg_cnt = se_cmd->t_data_nents; cmd->sg = se_cmd->t_data_sg; cmd->offset = 0; - cmd->cmd_flags |= BIT_3; cmd->prot_sg_cnt = se_cmd->t_prot_nents; cmd->prot_sg = se_cmd->t_prot_sg; @@ -571,7 +569,6 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd) cmd->sg_cnt = 0; cmd->offset = 0; cmd->dma_data_direction = target_reverse_dma_direction(se_cmd); - cmd->aborted = (se_cmd->transport_state & CMD_T_ABORTED); if (cmd->cmd_flags & BIT_5) { pr_crit("Bit_5 already set for cmd = %p.\n", cmd); dump_stack(); @@ -636,14 +633,7 @@ static void tcm_qla2xxx_aborted_task(struct se_cmd *se_cmd) { struct qla_tgt_cmd *cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd); - struct scsi_qla_host *vha = cmd->vha; - struct qla_hw_data *ha = vha->hw; - - if (!cmd->sg_mapped) - return; - - pci_unmap_sg(ha->pdev, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction); - cmd->sg_mapped = 0; + qlt_abort_cmd(cmd); } static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *, @@ -1149,9 +1139,7 @@ static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_s_id( return NULL; } - key = (((unsigned long)s_id[0] << 16) | - ((unsigned long)s_id[1] << 8) | - (unsigned long)s_id[2]); + key = sid_to_key(s_id); pr_debug("find_sess_by_s_id: 0x%06x\n", key); se_nacl = btree_lookup32(&lport->lport_fcport_map, key); @@ -1186,9 +1174,7 @@ static void tcm_qla2xxx_set_sess_by_s_id( void *slot; int rc; - key = (((unsigned long)s_id[0] << 16) | - ((unsigned long)s_id[1] << 8) | - (unsigned long)s_id[2]); + key = sid_to_key(s_id); pr_debug("set_sess_by_s_id: %06x\n", key); slot = btree_lookup32(&lport->lport_fcport_map, key); @@ -1544,6 +1530,10 @@ static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id, } sess->conf_compl_supported = conf_compl_supported; + + /* Reset logout parameters to default */ + sess->logout_on_delete = 1; + sess->keep_nport_handle = 0; } /* diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 106884a5444e..cfadccef045c 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -944,7 +944,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, scmd->sdb.length); scmd->sdb.table.sgl = &ses->sense_sgl; scmd->sc_data_direction = DMA_FROM_DEVICE; - scmd->sdb.table.nents = 1; + scmd->sdb.table.nents = scmd->sdb.table.orig_nents = 1; scmd->cmnd[0] = REQUEST_SENSE; scmd->cmnd[4] = scmd->sdb.length; scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index b1a263137a23..448ebdaa3d69 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -583,7 +583,7 @@ static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask) static void scsi_free_sgtable(struct scsi_data_buffer *sdb, bool mq) { - if (mq && sdb->table.nents <= SCSI_MAX_SG_SEGMENTS) + if (mq && sdb->table.orig_nents <= SCSI_MAX_SG_SEGMENTS) return; __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free); } @@ -597,8 +597,8 @@ static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents, bool mq) if (mq) { if (nents <= SCSI_MAX_SG_SEGMENTS) { - sdb->table.nents = nents; - sg_init_table(sdb->table.sgl, sdb->table.nents); + sdb->table.nents = sdb->table.orig_nents = nents; + sg_init_table(sdb->table.sgl, nents); return 0; } first_chunk = sdb->table.sgl; diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 1ac38e73df7e..9ad41168d26d 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -859,7 +859,7 @@ sdev_store_queue_depth(struct device *dev, struct device_attribute *attr, depth = simple_strtoul(buf, NULL, 0); - if (depth < 1 || depth > sht->can_queue) + if (depth < 1 || depth > sdev->host->can_queue) return -EINVAL; retval = sht->change_queue_depth(sdev, depth); diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c index a85292b1d09d..e3cd3ece4412 100644 --- a/drivers/scsi/scsi_transport_srp.c +++ b/drivers/scsi/scsi_transport_srp.c @@ -203,7 +203,7 @@ static ssize_t srp_show_tmo(char *buf, int tmo) return tmo >= 0 ? sprintf(buf, "%d\n", tmo) : sprintf(buf, "off\n"); } -static int srp_parse_tmo(int *tmo, const char *buf) +int srp_parse_tmo(int *tmo, const char *buf) { int res = 0; @@ -214,6 +214,7 @@ static int srp_parse_tmo(int *tmo, const char *buf) return res; } +EXPORT_SYMBOL(srp_parse_tmo); static ssize_t show_reconnect_delay(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 3f25b8fa921d..871f3553987d 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -1329,9 +1329,9 @@ static int st_open(struct inode *inode, struct file *filp) spin_lock(&st_use_lock); STp->in_use = 0; spin_unlock(&st_use_lock); - scsi_tape_put(STp); if (resumed) scsi_autopm_put_device(STp->device); + scsi_tape_put(STp); return retval; } diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 285f77544c36..7dbbb29d24c6 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -949,7 +949,7 @@ static int virtscsi_probe(struct virtio_device *vdev) { struct Scsi_Host *shost; struct virtio_scsi *vscsi; - int err, host_prot; + int err; u32 sg_elems, num_targets; u32 cmd_per_lun; u32 num_queues; @@ -1009,6 +1009,8 @@ static int virtscsi_probe(struct virtio_device *vdev) #ifdef CONFIG_BLK_DEV_INTEGRITY if (virtio_has_feature(vdev, VIRTIO_SCSI_F_T10_PI)) { + int host_prot; + host_prot = SHOST_DIF_TYPE1_PROTECTION | SHOST_DIF_TYPE2_PROTECTION | SHOST_DIF_TYPE3_PROTECTION | SHOST_DIX_TYPE1_PROTECTION | SHOST_DIX_TYPE2_PROTECTION | SHOST_DIX_TYPE3_PROTECTION; diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 0cae1694014d..b0f30fb68914 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -612,7 +612,7 @@ config SPI_XTENSA_XTFPGA config SPI_ZYNQMP_GQSPI tristate "Xilinx ZynqMP GQSPI controller" - depends on SPI_MASTER + depends on SPI_MASTER && HAS_DMA help Enables Xilinx GQSPI controller driver for Zynq UltraScale+ MPSoC. diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index 788e2b176a4f..acce90ac7371 100644 --- a/drivers/spi/spi-img-spfi.c +++ b/drivers/spi/spi-img-spfi.c @@ -40,6 +40,7 @@ #define SPFI_CONTROL_SOFT_RESET BIT(11) #define SPFI_CONTROL_SEND_DMA BIT(10) #define SPFI_CONTROL_GET_DMA BIT(9) +#define SPFI_CONTROL_SE BIT(8) #define SPFI_CONTROL_TMODE_SHIFT 5 #define SPFI_CONTROL_TMODE_MASK 0x7 #define SPFI_CONTROL_TMODE_SINGLE 0 @@ -491,6 +492,7 @@ static void img_spfi_config(struct spi_master *master, struct spi_device *spi, else if (xfer->tx_nbits == SPI_NBITS_QUAD && xfer->rx_nbits == SPI_NBITS_QUAD) val |= SPFI_CONTROL_TMODE_QUAD << SPFI_CONTROL_TMODE_SHIFT; + val |= SPFI_CONTROL_SE; spfi_writel(spfi, val, SPFI_CONTROL); } diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index eb7d3a6fb14c..f9deb84e4e55 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -201,8 +201,9 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, { struct spi_imx_data *spi_imx = spi_master_get_devdata(master); - if (spi_imx->dma_is_inited && (transfer->len > spi_imx->rx_wml) - && (transfer->len > spi_imx->tx_wml)) + if (spi_imx->dma_is_inited + && transfer->len > spi_imx->rx_wml * sizeof(u32) + && transfer->len > spi_imx->tx_wml * sizeof(u32)) return true; return false; } diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index 87b20a511a6b..f23f36ebaf3d 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -214,6 +214,7 @@ static void zynqmp_gqspi_selectslave(struct zynqmp_qspi *instanceptr, case GQSPI_SELECT_FLASH_CS_BOTH: instanceptr->genfifocs = GQSPI_GENFIFO_CS_LOWER | GQSPI_GENFIFO_CS_UPPER; + break; case GQSPI_SELECT_FLASH_CS_UPPER: instanceptr->genfifocs = GQSPI_GENFIFO_CS_UPPER; break; diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index dd616ff0ffc5..c7de64171c45 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -693,6 +693,7 @@ static struct class *spidev_class; #ifdef CONFIG_OF static const struct of_device_id spidev_dt_ids[] = { { .compatible = "rohm,dh2228fv" }, + { .compatible = "lineartechnology,ltc2488" }, {}, }; MODULE_DEVICE_TABLE(of, spidev_dt_ids); diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 7f6cae5beb90..e29293c0c71e 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -56,8 +56,6 @@ source "drivers/staging/vt6656/Kconfig" source "drivers/staging/iio/Kconfig" -source "drivers/staging/sm7xxfb/Kconfig" - source "drivers/staging/sm750fb/Kconfig" source "drivers/staging/xgifb/Kconfig" @@ -78,8 +76,6 @@ source "drivers/staging/android/Kconfig" source "drivers/staging/board/Kconfig" -source "drivers/staging/ozwpan/Kconfig" - source "drivers/staging/gdm72xx/Kconfig" source "drivers/staging/gdm724x/Kconfig" @@ -112,4 +108,6 @@ source "drivers/staging/fsl-mc/Kconfig" source "drivers/staging/wilc1000/Kconfig" +source "drivers/staging/most/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 347f6477aa3e..50824dde2c09 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -22,7 +22,6 @@ obj-$(CONFIG_VT6655) += vt6655/ obj-$(CONFIG_VT6656) += vt6656/ obj-$(CONFIG_VME_BUS) += vme/ obj-$(CONFIG_IIO) += iio/ -obj-$(CONFIG_FB_SM7XX) += sm7xxfb/ obj-$(CONFIG_FB_SM750) += sm750fb/ obj-$(CONFIG_FB_XGI) += xgifb/ obj-$(CONFIG_USB_EMXX) += emxx_udc/ @@ -32,7 +31,6 @@ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/ obj-$(CONFIG_MFD_NVEC) += nvec/ obj-$(CONFIG_ANDROID) += android/ obj-$(CONFIG_STAGING_BOARD) += board/ -obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/ obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/ obj-$(CONFIG_LTE_GDM724X) += gdm724x/ obj-$(CONFIG_FIREWIRE_SERIAL) += fwserial/ @@ -48,3 +46,4 @@ obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/ obj-$(CONFIG_FB_TFT) += fbtft/ obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/ obj-$(CONFIG_WILC1000) += wilc1000/ +obj-$(CONFIG_MOST) += most/ diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 24d657b3ab99..68307121c9c1 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -20,7 +20,8 @@ config ANDROID_TIMED_OUTPUT config ANDROID_TIMED_GPIO tristate "Android timed gpio driver" - depends on GPIOLIB && ANDROID_TIMED_OUTPUT + depends on GPIOLIB || COMPILE_TEST + depends on ANDROID_TIMED_OUTPUT default n ---help--- Unlike generic gpio is to allow programs to access and manipulate gpio diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index c5c037ccf32c..cefc208c313a 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -388,7 +388,7 @@ static int ashmem_mmap(struct file *file, struct vm_area_struct *vma) /* ... and allocate the backing shmem file */ vmfile = shmem_file_setup(name, asma->size, vma->vm_flags); - if (unlikely(IS_ERR(vmfile))) { + if (IS_ERR(vmfile)) { ret = PTR_ERR(vmfile); goto out; } @@ -660,7 +660,7 @@ restart: if (page_range_subsumed_by_range(range, pgstart, pgend)) return 0; if (page_range_in_range(range, pgstart, pgend)) { - pgstart = min_t(size_t, range->pgstart, pgstart), + pgstart = min_t(size_t, range->pgstart, pgstart); pgend = max_t(size_t, range->pgend, pgend); purged |= range->purged; range_del(range); diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index f4211f1be488..0b2448c32495 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -73,8 +73,8 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, if (!info->table) goto free_mem; - if (dma_common_get_sgtable - (dev, info->table, info->cpu_addr, info->handle, len)) + if (dma_get_sgtable(dev, info->table, info->cpu_addr, info->handle, + len)) goto free_table; /* keep this for memory release */ buffer->priv_virt = info; diff --git a/drivers/staging/android/timed_gpio.c b/drivers/staging/android/timed_gpio.c index 938a35cd99bb..ce11726f1a6c 100644 --- a/drivers/staging/android/timed_gpio.c +++ b/drivers/staging/android/timed_gpio.c @@ -61,9 +61,9 @@ static int gpio_get_time(struct timed_output_dev *dev) static void gpio_enable(struct timed_output_dev *dev, int value) { - struct timed_gpio_data *data = + struct timed_gpio_data *data = container_of(dev, struct timed_gpio_data, dev); - unsigned long flags; + unsigned long flags; spin_lock_irqsave(&data->lock, flags); diff --git a/drivers/staging/board/Kconfig b/drivers/staging/board/Kconfig index b8ee81840666..3f287c48e082 100644 --- a/drivers/staging/board/Kconfig +++ b/drivers/staging/board/Kconfig @@ -1,6 +1,6 @@ config STAGING_BOARD bool "Staging Board Support" - depends on OF_ADDRESS + depends on OF_ADDRESS && OF_IRQ && CLKDEV_LOOKUP help Select to enable per-board staging support code. diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index ed0b60c925de..b03bc6639f79 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -820,7 +820,7 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it) "driver '%s' does not support attach using comedi_config\n", driv->driver_name); module_put(driv->module); - ret = -ENOSYS; + ret = -EIO; goto out; } dev->driver = driv; diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index d7cf4b153f7c..056bca9c67d5 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -1032,8 +1032,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* check that clock setting is valid */ if (it->options[3]) { - if (it->options[3] != 0 && - it->options[3] != 1 && it->options[3] != 10) { + if (it->options[3] != 1 && it->options[3] != 10) { dev_err(dev->class_dev, "Invalid option. Master clock must be set to 1 or 10 (MHz)\n"); return -EINVAL; diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index bfa42620a3f6..940781183fac 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -1266,6 +1266,7 @@ static const struct das1800_board *das1800_probe(struct comedi_device *dev) if (index == das1801hc || index == das1802hc) return board; index = das1801hc; + break; default: dev_err(dev->class_dev, "Board model: probe returned 0x%x (unknown, please report)\n", diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index a8f3ca48784b..5aa1780cf42b 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -1,43 +1,41 @@ /* - comedi/drivers/me4000.c - Source code for the Meilhaus ME-4000 board family. - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + * me4000.c + * Source code for the Meilhaus ME-4000 board family. + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. */ -/* -Driver: me4000 -Description: Meilhaus ME-4000 series boards -Devices: [Meilhaus] ME-4650 (me4000), ME-4670i, ME-4680, ME-4680i, ME-4680is -Author: gg (Guenter Gebhardt <g.gebhardt@meilhaus.com>) -Updated: Mon, 18 Mar 2002 15:34:01 -0800 -Status: broken (no support for loading firmware) - -Supports: - - - Analog Input - - Analog Output - - Digital I/O - - Counter - -Configuration Options: not applicable, uses PCI auto config - -The firmware required by these boards is available in the -comedi_nonfree_firmware tarball available from -http://www.comedi.org. However, the driver's support for -loading the firmware through comedi_config is currently -broken. +/* + * Driver: me4000 + * Description: Meilhaus ME-4000 series boards + * Devices: [Meilhaus] ME-4650 (me4000), ME-4670i, ME-4680, ME-4680i, + * ME-4680is + * Author: gg (Guenter Gebhardt <g.gebhardt@meilhaus.com>) + * Updated: Mon, 18 Mar 2002 15:34:01 -0800 + * Status: untested + * + * Supports: + * - Analog Input + * - Analog Output + * - Digital I/O + * - Counter + * + * Configuration Options: not applicable, uses PCI auto config + * + * The firmware required by these boards is available in the + * comedi_nonfree_firmware tarball available from + * http://www.comedi.org. */ #include <linux/module.h> @@ -57,66 +55,61 @@ broken. #define ME4000_AO_CHAN(x) ((x) * 0x18) #define ME4000_AO_CTRL_REG(x) (0x00 + ME4000_AO_CHAN(x)) -#define ME4000_AO_CTRL_BIT_MODE_0 (1 << 0) -#define ME4000_AO_CTRL_BIT_MODE_1 (1 << 1) -#define ME4000_AO_CTRL_MASK_MODE (3 << 0) -#define ME4000_AO_CTRL_BIT_STOP (1 << 2) -#define ME4000_AO_CTRL_BIT_ENABLE_FIFO (1 << 3) -#define ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG (1 << 4) -#define ME4000_AO_CTRL_BIT_EX_TRIG_EDGE (1 << 5) -#define ME4000_AO_CTRL_BIT_IMMEDIATE_STOP (1 << 7) -#define ME4000_AO_CTRL_BIT_ENABLE_DO (1 << 8) -#define ME4000_AO_CTRL_BIT_ENABLE_IRQ (1 << 9) -#define ME4000_AO_CTRL_BIT_RESET_IRQ (1 << 10) +#define ME4000_AO_CTRL_MODE_0 BIT(0) +#define ME4000_AO_CTRL_MODE_1 BIT(1) +#define ME4000_AO_CTRL_STOP BIT(2) +#define ME4000_AO_CTRL_ENABLE_FIFO BIT(3) +#define ME4000_AO_CTRL_ENABLE_EX_TRIG BIT(4) +#define ME4000_AO_CTRL_EX_TRIG_EDGE BIT(5) +#define ME4000_AO_CTRL_IMMEDIATE_STOP BIT(7) +#define ME4000_AO_CTRL_ENABLE_DO BIT(8) +#define ME4000_AO_CTRL_ENABLE_IRQ BIT(9) +#define ME4000_AO_CTRL_RESET_IRQ BIT(10) #define ME4000_AO_STATUS_REG(x) (0x04 + ME4000_AO_CHAN(x)) -#define ME4000_AO_STATUS_BIT_FSM (1 << 0) -#define ME4000_AO_STATUS_BIT_FF (1 << 1) -#define ME4000_AO_STATUS_BIT_HF (1 << 2) -#define ME4000_AO_STATUS_BIT_EF (1 << 3) +#define ME4000_AO_STATUS_FSM BIT(0) +#define ME4000_AO_STATUS_FF BIT(1) +#define ME4000_AO_STATUS_HF BIT(2) +#define ME4000_AO_STATUS_EF BIT(3) #define ME4000_AO_FIFO_REG(x) (0x08 + ME4000_AO_CHAN(x)) #define ME4000_AO_SINGLE_REG(x) (0x0c + ME4000_AO_CHAN(x)) #define ME4000_AO_TIMER_REG(x) (0x10 + ME4000_AO_CHAN(x)) #define ME4000_AI_CTRL_REG 0x74 #define ME4000_AI_STATUS_REG 0x74 -#define ME4000_AI_CTRL_BIT_MODE_0 (1 << 0) -#define ME4000_AI_CTRL_BIT_MODE_1 (1 << 1) -#define ME4000_AI_CTRL_BIT_MODE_2 (1 << 2) -#define ME4000_AI_CTRL_BIT_SAMPLE_HOLD (1 << 3) -#define ME4000_AI_CTRL_BIT_IMMEDIATE_STOP (1 << 4) -#define ME4000_AI_CTRL_BIT_STOP (1 << 5) -#define ME4000_AI_CTRL_BIT_CHANNEL_FIFO (1 << 6) -#define ME4000_AI_CTRL_BIT_DATA_FIFO (1 << 7) -#define ME4000_AI_CTRL_BIT_FULLSCALE (1 << 8) -#define ME4000_AI_CTRL_BIT_OFFSET (1 << 9) -#define ME4000_AI_CTRL_BIT_EX_TRIG_ANALOG (1 << 10) -#define ME4000_AI_CTRL_BIT_EX_TRIG (1 << 11) -#define ME4000_AI_CTRL_BIT_EX_TRIG_FALLING (1 << 12) -#define ME4000_AI_CTRL_BIT_EX_IRQ (1 << 13) -#define ME4000_AI_CTRL_BIT_EX_IRQ_RESET (1 << 14) -#define ME4000_AI_CTRL_BIT_LE_IRQ (1 << 15) -#define ME4000_AI_CTRL_BIT_LE_IRQ_RESET (1 << 16) -#define ME4000_AI_CTRL_BIT_HF_IRQ (1 << 17) -#define ME4000_AI_CTRL_BIT_HF_IRQ_RESET (1 << 18) -#define ME4000_AI_CTRL_BIT_SC_IRQ (1 << 19) -#define ME4000_AI_CTRL_BIT_SC_IRQ_RESET (1 << 20) -#define ME4000_AI_CTRL_BIT_SC_RELOAD (1 << 21) -#define ME4000_AI_STATUS_BIT_EF_CHANNEL (1 << 22) -#define ME4000_AI_STATUS_BIT_HF_CHANNEL (1 << 23) -#define ME4000_AI_STATUS_BIT_FF_CHANNEL (1 << 24) -#define ME4000_AI_STATUS_BIT_EF_DATA (1 << 25) -#define ME4000_AI_STATUS_BIT_HF_DATA (1 << 26) -#define ME4000_AI_STATUS_BIT_FF_DATA (1 << 27) -#define ME4000_AI_STATUS_BIT_LE (1 << 28) -#define ME4000_AI_STATUS_BIT_FSM (1 << 29) -#define ME4000_AI_CTRL_BIT_EX_TRIG_BOTH (1 << 31) +#define ME4000_AI_CTRL_MODE_0 BIT(0) +#define ME4000_AI_CTRL_MODE_1 BIT(1) +#define ME4000_AI_CTRL_MODE_2 BIT(2) +#define ME4000_AI_CTRL_SAMPLE_HOLD BIT(3) +#define ME4000_AI_CTRL_IMMEDIATE_STOP BIT(4) +#define ME4000_AI_CTRL_STOP BIT(5) +#define ME4000_AI_CTRL_CHANNEL_FIFO BIT(6) +#define ME4000_AI_CTRL_DATA_FIFO BIT(7) +#define ME4000_AI_CTRL_FULLSCALE BIT(8) +#define ME4000_AI_CTRL_OFFSET BIT(9) +#define ME4000_AI_CTRL_EX_TRIG_ANALOG BIT(10) +#define ME4000_AI_CTRL_EX_TRIG BIT(11) +#define ME4000_AI_CTRL_EX_TRIG_FALLING BIT(12) +#define ME4000_AI_CTRL_EX_IRQ BIT(13) +#define ME4000_AI_CTRL_EX_IRQ_RESET BIT(14) +#define ME4000_AI_CTRL_LE_IRQ BIT(15) +#define ME4000_AI_CTRL_LE_IRQ_RESET BIT(16) +#define ME4000_AI_CTRL_HF_IRQ BIT(17) +#define ME4000_AI_CTRL_HF_IRQ_RESET BIT(18) +#define ME4000_AI_CTRL_SC_IRQ BIT(19) +#define ME4000_AI_CTRL_SC_IRQ_RESET BIT(20) +#define ME4000_AI_CTRL_SC_RELOAD BIT(21) +#define ME4000_AI_STATUS_EF_CHANNEL BIT(22) +#define ME4000_AI_STATUS_HF_CHANNEL BIT(23) +#define ME4000_AI_STATUS_FF_CHANNEL BIT(24) +#define ME4000_AI_STATUS_EF_DATA BIT(25) +#define ME4000_AI_STATUS_HF_DATA BIT(26) +#define ME4000_AI_STATUS_FF_DATA BIT(27) +#define ME4000_AI_STATUS_LE BIT(28) +#define ME4000_AI_STATUS_FSM BIT(29) +#define ME4000_AI_CTRL_EX_TRIG_BOTH BIT(31) #define ME4000_AI_CHANNEL_LIST_REG 0x78 -#define ME4000_AI_LIST_INPUT_SINGLE_ENDED (0 << 5) -#define ME4000_AI_LIST_INPUT_DIFFERENTIAL (1 << 5) -#define ME4000_AI_LIST_RANGE_BIPOLAR_10 (0 << 6) -#define ME4000_AI_LIST_RANGE_BIPOLAR_2_5 (1 << 6) -#define ME4000_AI_LIST_RANGE_UNIPOLAR_10 (2 << 6) -#define ME4000_AI_LIST_RANGE_UNIPOLAR_2_5 (3 << 6) -#define ME4000_AI_LIST_LAST_ENTRY (1 << 8) +#define ME4000_AI_LIST_INPUT_DIFFERENTIAL BIT(5) +#define ME4000_AI_LIST_RANGE(x) ((3 - ((x) & 3)) << 6) +#define ME4000_AI_LIST_LAST_ENTRY BIT(8) #define ME4000_AI_DATA_REG 0x7c #define ME4000_AI_CHAN_TIMER_REG 0x80 #define ME4000_AI_CHAN_PRE_TIMER_REG 0x84 @@ -126,14 +119,14 @@ broken. #define ME4000_AI_SCAN_PRE_TIMER_HIGH_REG 0x94 #define ME4000_AI_START_REG 0x98 #define ME4000_IRQ_STATUS_REG 0x9c -#define ME4000_IRQ_STATUS_BIT_EX (1 << 0) -#define ME4000_IRQ_STATUS_BIT_LE (1 << 1) -#define ME4000_IRQ_STATUS_BIT_AI_HF (1 << 2) -#define ME4000_IRQ_STATUS_BIT_AO_0_HF (1 << 3) -#define ME4000_IRQ_STATUS_BIT_AO_1_HF (1 << 4) -#define ME4000_IRQ_STATUS_BIT_AO_2_HF (1 << 5) -#define ME4000_IRQ_STATUS_BIT_AO_3_HF (1 << 6) -#define ME4000_IRQ_STATUS_BIT_SC (1 << 7) +#define ME4000_IRQ_STATUS_EX BIT(0) +#define ME4000_IRQ_STATUS_LE BIT(1) +#define ME4000_IRQ_STATUS_AI_HF BIT(2) +#define ME4000_IRQ_STATUS_AO_0_HF BIT(3) +#define ME4000_IRQ_STATUS_AO_1_HF BIT(4) +#define ME4000_IRQ_STATUS_AO_2_HF BIT(5) +#define ME4000_IRQ_STATUS_AO_3_HF BIT(6) +#define ME4000_IRQ_STATUS_SC BIT(7) #define ME4000_DIO_PORT_0_REG 0xa0 #define ME4000_DIO_PORT_1_REG 0xa4 #define ME4000_DIO_PORT_2_REG 0xa8 @@ -141,20 +134,20 @@ broken. #define ME4000_DIO_DIR_REG 0xb0 #define ME4000_AO_LOADSETREG_XX 0xb4 #define ME4000_DIO_CTRL_REG 0xb8 -#define ME4000_DIO_CTRL_BIT_MODE_0 (1 << 0) -#define ME4000_DIO_CTRL_BIT_MODE_1 (1 << 1) -#define ME4000_DIO_CTRL_BIT_MODE_2 (1 << 2) -#define ME4000_DIO_CTRL_BIT_MODE_3 (1 << 3) -#define ME4000_DIO_CTRL_BIT_MODE_4 (1 << 4) -#define ME4000_DIO_CTRL_BIT_MODE_5 (1 << 5) -#define ME4000_DIO_CTRL_BIT_MODE_6 (1 << 6) -#define ME4000_DIO_CTRL_BIT_MODE_7 (1 << 7) -#define ME4000_DIO_CTRL_BIT_FUNCTION_0 (1 << 8) -#define ME4000_DIO_CTRL_BIT_FUNCTION_1 (1 << 9) -#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_0 (1 << 10) -#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_1 (1 << 11) -#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_2 (1 << 12) -#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_3 (1 << 13) +#define ME4000_DIO_CTRL_MODE_0 BIT(0) +#define ME4000_DIO_CTRL_MODE_1 BIT(1) +#define ME4000_DIO_CTRL_MODE_2 BIT(2) +#define ME4000_DIO_CTRL_MODE_3 BIT(3) +#define ME4000_DIO_CTRL_MODE_4 BIT(4) +#define ME4000_DIO_CTRL_MODE_5 BIT(5) +#define ME4000_DIO_CTRL_MODE_6 BIT(6) +#define ME4000_DIO_CTRL_MODE_7 BIT(7) +#define ME4000_DIO_CTRL_FUNCTION_0 BIT(8) +#define ME4000_DIO_CTRL_FUNCTION_1 BIT(9) +#define ME4000_DIO_CTRL_FIFO_HIGH_0 BIT(10) +#define ME4000_DIO_CTRL_FIFO_HIGH_1 BIT(11) +#define ME4000_DIO_CTRL_FIFO_HIGH_2 BIT(12) +#define ME4000_DIO_CTRL_FIFO_HIGH_3 BIT(13) #define ME4000_AO_DEMUX_ADJUST_REG 0xbc #define ME4000_AO_DEMUX_ADJUST_VALUE 0x4c #define ME4000_AI_SAMPLE_COUNTER_REG 0xc0 @@ -166,8 +159,12 @@ broken. #define ME4000_AI_CHANNEL_LIST_COUNT 1024 -struct me4000_info { +struct me4000_private { unsigned long plx_regbase; + unsigned int ai_ctrl_mode; + unsigned int ai_init_ticks; + unsigned int ai_scan_ticks; + unsigned int ai_chan_ticks; }; enum me4000_boardid { @@ -188,134 +185,126 @@ enum me4000_boardid { struct me4000_board { const char *name; - int ao_nchan; - int ao_fifo; int ai_nchan; - int ai_diff_nchan; - int ai_sh_nchan; - int ex_trig_analog; - int dio_nchan; - int has_counter; + unsigned int can_do_diff_ai:1; + unsigned int can_do_sh_ai:1; /* sample & hold (8 channels) */ + unsigned int ex_trig_analog:1; + unsigned int has_ao:1; + unsigned int has_ao_fifo:1; + unsigned int has_counter:1; }; static const struct me4000_board me4000_boards[] = { [BOARD_ME4650] = { .name = "ME-4650", .ai_nchan = 16, - .dio_nchan = 32, }, [BOARD_ME4660] = { .name = "ME-4660", .ai_nchan = 32, - .ai_diff_nchan = 16, - .dio_nchan = 32, + .can_do_diff_ai = 1, .has_counter = 1, }, [BOARD_ME4660I] = { .name = "ME-4660i", .ai_nchan = 32, - .ai_diff_nchan = 16, - .dio_nchan = 32, + .can_do_diff_ai = 1, .has_counter = 1, }, [BOARD_ME4660S] = { .name = "ME-4660s", .ai_nchan = 32, - .ai_diff_nchan = 16, - .ai_sh_nchan = 8, - .dio_nchan = 32, + .can_do_diff_ai = 1, + .can_do_sh_ai = 1, .has_counter = 1, }, [BOARD_ME4660IS] = { .name = "ME-4660is", .ai_nchan = 32, - .ai_diff_nchan = 16, - .ai_sh_nchan = 8, - .dio_nchan = 32, + .can_do_diff_ai = 1, + .can_do_sh_ai = 1, .has_counter = 1, }, [BOARD_ME4670] = { .name = "ME-4670", - .ao_nchan = 4, .ai_nchan = 32, - .ai_diff_nchan = 16, + .can_do_diff_ai = 1, .ex_trig_analog = 1, - .dio_nchan = 32, + .has_ao = 1, .has_counter = 1, }, [BOARD_ME4670I] = { .name = "ME-4670i", - .ao_nchan = 4, .ai_nchan = 32, - .ai_diff_nchan = 16, + .can_do_diff_ai = 1, .ex_trig_analog = 1, - .dio_nchan = 32, + .has_ao = 1, .has_counter = 1, }, [BOARD_ME4670S] = { .name = "ME-4670s", - .ao_nchan = 4, .ai_nchan = 32, - .ai_diff_nchan = 16, - .ai_sh_nchan = 8, + .can_do_diff_ai = 1, + .can_do_sh_ai = 1, .ex_trig_analog = 1, - .dio_nchan = 32, + .has_ao = 1, .has_counter = 1, }, [BOARD_ME4670IS] = { .name = "ME-4670is", - .ao_nchan = 4, .ai_nchan = 32, - .ai_diff_nchan = 16, - .ai_sh_nchan = 8, + .can_do_diff_ai = 1, + .can_do_sh_ai = 1, .ex_trig_analog = 1, - .dio_nchan = 32, + .has_ao = 1, .has_counter = 1, }, [BOARD_ME4680] = { .name = "ME-4680", - .ao_nchan = 4, - .ao_fifo = 4, .ai_nchan = 32, - .ai_diff_nchan = 16, + .can_do_diff_ai = 1, .ex_trig_analog = 1, - .dio_nchan = 32, + .has_ao = 1, + .has_ao_fifo = 1, .has_counter = 1, }, [BOARD_ME4680I] = { .name = "ME-4680i", - .ao_nchan = 4, - .ao_fifo = 4, .ai_nchan = 32, - .ai_diff_nchan = 16, + .can_do_diff_ai = 1, .ex_trig_analog = 1, - .dio_nchan = 32, + .has_ao = 1, + .has_ao_fifo = 1, .has_counter = 1, }, [BOARD_ME4680S] = { .name = "ME-4680s", - .ao_nchan = 4, - .ao_fifo = 4, .ai_nchan = 32, - .ai_diff_nchan = 16, - .ai_sh_nchan = 8, + .can_do_diff_ai = 1, + .can_do_sh_ai = 1, .ex_trig_analog = 1, - .dio_nchan = 32, + .has_ao = 1, + .has_ao_fifo = 1, .has_counter = 1, }, [BOARD_ME4680IS] = { .name = "ME-4680is", - .ao_nchan = 4, - .ao_fifo = 4, .ai_nchan = 32, - .ai_diff_nchan = 16, - .ai_sh_nchan = 8, + .can_do_diff_ai = 1, + .can_do_sh_ai = 1, .ex_trig_analog = 1, - .dio_nchan = 32, + .has_ao = 1, + .has_ao_fifo = 1, .has_counter = 1, }, }; +/* + * NOTE: the ranges here are inverted compared to the values + * written to the ME4000_AI_CHANNEL_LIST_REG, + * + * The ME4000_AI_LIST_RANGE() macro handles the inversion. + */ static const struct comedi_lrange me4000_ai_range = { 4, { UNI_RANGE(2.5), @@ -330,7 +319,7 @@ static int me4000_xilinx_download(struct comedi_device *dev, unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - struct me4000_info *info = dev->private; + struct me4000_private *devpriv = dev->private; unsigned long xilinx_iobase = pci_resource_start(pcidev, 5); unsigned int file_length; unsigned int val; @@ -343,42 +332,42 @@ static int me4000_xilinx_download(struct comedi_device *dev, * Set PLX local interrupt 2 polarity to high. * Interrupt is thrown by init pin of xilinx. */ - outl(PLX9052_INTCSR_LI2POL, info->plx_regbase + PLX9052_INTCSR); + outl(PLX9052_INTCSR_LI2POL, devpriv->plx_regbase + PLX9052_INTCSR); /* Set /CS and /WRITE of the Xilinx */ - val = inl(info->plx_regbase + PLX9052_CNTRL); + val = inl(devpriv->plx_regbase + PLX9052_CNTRL); val |= PLX9052_CNTRL_UIO2_DATA; - outl(val, info->plx_regbase + PLX9052_CNTRL); + outl(val, devpriv->plx_regbase + PLX9052_CNTRL); /* Init Xilinx with CS1 */ inb(xilinx_iobase + 0xC8); /* Wait until /INIT pin is set */ - udelay(20); - val = inl(info->plx_regbase + PLX9052_INTCSR); + usleep_range(20, 1000); + val = inl(devpriv->plx_regbase + PLX9052_INTCSR); if (!(val & PLX9052_INTCSR_LI2STAT)) { dev_err(dev->class_dev, "Can't init Xilinx\n"); return -EIO; } /* Reset /CS and /WRITE of the Xilinx */ - val = inl(info->plx_regbase + PLX9052_CNTRL); + val = inl(devpriv->plx_regbase + PLX9052_CNTRL); val &= ~PLX9052_CNTRL_UIO2_DATA; - outl(val, info->plx_regbase + PLX9052_CNTRL); + outl(val, devpriv->plx_regbase + PLX9052_CNTRL); /* Download Xilinx firmware */ file_length = (((unsigned int)data[0] & 0xff) << 24) + (((unsigned int)data[1] & 0xff) << 16) + (((unsigned int)data[2] & 0xff) << 8) + ((unsigned int)data[3] & 0xff); - udelay(10); + usleep_range(10, 1000); for (i = 0; i < file_length; i++) { outb(data[16 + i], xilinx_iobase); - udelay(10); + usleep_range(10, 1000); /* Check if BUSY flag is low */ - val = inl(info->plx_regbase + PLX9052_CNTRL); + val = inl(devpriv->plx_regbase + PLX9052_CNTRL); if (val & PLX9052_CNTRL_UIO1_DATA) { dev_err(dev->class_dev, "Xilinx is still busy (i = %d)\n", i); @@ -387,7 +376,7 @@ static int me4000_xilinx_download(struct comedi_device *dev, } /* If done flag is high download was successful */ - val = inl(info->plx_regbase + PLX9052_CNTRL); + val = inl(devpriv->plx_regbase + PLX9052_CNTRL); if (!(val & PLX9052_CNTRL_UIO0_DATA)) { dev_err(dev->class_dev, "DONE flag is not set\n"); dev_err(dev->class_dev, "Download not successful\n"); @@ -395,44 +384,53 @@ static int me4000_xilinx_download(struct comedi_device *dev, } /* Set /CS and /WRITE */ - val = inl(info->plx_regbase + PLX9052_CNTRL); + val = inl(devpriv->plx_regbase + PLX9052_CNTRL); val |= PLX9052_CNTRL_UIO2_DATA; - outl(val, info->plx_regbase + PLX9052_CNTRL); + outl(val, devpriv->plx_regbase + PLX9052_CNTRL); return 0; } +static void me4000_ai_reset(struct comedi_device *dev) +{ + unsigned int ctrl; + + /* Stop any running conversion */ + ctrl = inl(dev->iobase + ME4000_AI_CTRL_REG); + ctrl |= ME4000_AI_CTRL_STOP | ME4000_AI_CTRL_IMMEDIATE_STOP; + outl(ctrl, dev->iobase + ME4000_AI_CTRL_REG); + + /* Clear the control register */ + outl(0x0, dev->iobase + ME4000_AI_CTRL_REG); +} + static void me4000_reset(struct comedi_device *dev) { - struct me4000_info *info = dev->private; + struct me4000_private *devpriv = dev->private; unsigned int val; int chan; - /* Make a hardware reset */ - val = inl(info->plx_regbase + PLX9052_CNTRL); + /* Disable interrupts on the PLX */ + outl(0, devpriv->plx_regbase + PLX9052_INTCSR); + + /* Software reset the PLX */ + val = inl(devpriv->plx_regbase + PLX9052_CNTRL); val |= PLX9052_CNTRL_PCI_RESET; - outl(val, info->plx_regbase + PLX9052_CNTRL); + outl(val, devpriv->plx_regbase + PLX9052_CNTRL); val &= ~PLX9052_CNTRL_PCI_RESET; - outl(val, info->plx_regbase + PLX9052_CNTRL); + outl(val, devpriv->plx_regbase + PLX9052_CNTRL); /* 0x8000 to the DACs means an output voltage of 0V */ for (chan = 0; chan < 4; chan++) outl(0x8000, dev->iobase + ME4000_AO_SINGLE_REG(chan)); - /* Set both stop bits in the analog input control register */ - outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP, - dev->iobase + ME4000_AI_CTRL_REG); + me4000_ai_reset(dev); /* Set both stop bits in the analog output control register */ - val = ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP; + val = ME4000_AO_CTRL_IMMEDIATE_STOP | ME4000_AO_CTRL_STOP; for (chan = 0; chan < 4; chan++) outl(val, dev->iobase + ME4000_AO_CTRL_REG(chan)); - /* Enable interrupts on the PLX */ - outl(PLX9052_INTCSR_LI1ENAB | - PLX9052_INTCSR_LI1POL | - PLX9052_INTCSR_PCIENAB, info->plx_regbase + PLX9052_INTCSR); - /* Set the adustment register for AO demux */ outl(ME4000_AO_DEMUX_ADJUST_VALUE, dev->iobase + ME4000_AO_DEMUX_ADJUST_REG); @@ -445,96 +443,68 @@ static void me4000_reset(struct comedi_device *dev) outl(0x1, dev->iobase + ME4000_DIO_CTRL_REG); } -/*============================================================================= - Analog input section - ===========================================================================*/ - -static int me4000_ai_insn_read(struct comedi_device *dev, - struct comedi_subdevice *subdevice, - struct comedi_insn *insn, unsigned int *data) +static unsigned int me4000_ai_get_sample(struct comedi_device *dev, + struct comedi_subdevice *s) { - const struct me4000_board *board = dev->board_ptr; - int chan = CR_CHAN(insn->chanspec); - int rang = CR_RANGE(insn->chanspec); - int aref = CR_AREF(insn->chanspec); + unsigned int val; - unsigned int entry = 0; - unsigned int tmp; - unsigned int lval; + /* read two's complement value and munge to offset binary */ + val = inl(dev->iobase + ME4000_AI_DATA_REG); + return comedi_offset_munge(s, val); +} - if (insn->n == 0) { +static int me4000_ai_eoc(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned long context) +{ + unsigned int status; + + status = inl(dev->iobase + ME4000_AI_STATUS_REG); + if (status & ME4000_AI_STATUS_EF_DATA) return 0; - } else if (insn->n > 1) { - dev_err(dev->class_dev, "Invalid instruction length %d\n", - insn->n); - return -EINVAL; - } + return -EBUSY; +} - switch (rang) { - case 0: - entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5; - break; - case 1: - entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10; - break; - case 2: - entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5; - break; - case 3: - entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10; - break; - default: - dev_err(dev->class_dev, "Invalid range specified\n"); - return -EINVAL; - } +static int me4000_ai_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); + unsigned int aref = CR_AREF(insn->chanspec); + unsigned int entry; + int ret = 0; + int i; - switch (aref) { - case AREF_GROUND: - case AREF_COMMON: - if (chan >= board->ai_nchan) { + entry = chan | ME4000_AI_LIST_RANGE(range); + if (aref == AREF_DIFF) { + if (!(s->subdev_flags && SDF_DIFF)) { dev_err(dev->class_dev, - "Analog input is not available\n"); + "Differential inputs are not available\n"); return -EINVAL; } - entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan; - break; - case AREF_DIFF: - if (rang == 0 || rang == 1) { + if (!comedi_range_is_bipolar(s, range)) { dev_err(dev->class_dev, "Range must be bipolar when aref = diff\n"); return -EINVAL; } - if (chan >= board->ai_diff_nchan) { + if (chan >= (s->n_chan / 2)) { dev_err(dev->class_dev, "Analog input is not available\n"); return -EINVAL; } - entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan; - break; - default: - dev_err(dev->class_dev, "Invalid aref specified\n"); - return -EINVAL; + entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL; } entry |= ME4000_AI_LIST_LAST_ENTRY; - /* Clear channel list, data fifo and both stop bits */ - tmp = inl(dev->iobase + ME4000_AI_CTRL_REG); - tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO | - ME4000_AI_CTRL_BIT_DATA_FIFO | - ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP); - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); - - /* Set the acquisition mode to single */ - tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 | - ME4000_AI_CTRL_BIT_MODE_2); - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); - - /* Enable channel list and data fifo */ - tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO; - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + /* Enable channel list and data fifo for single acquisition mode */ + outl(ME4000_AI_CTRL_CHANNEL_FIFO | ME4000_AI_CTRL_DATA_FIFO, + dev->iobase + ME4000_AI_CTRL_REG); /* Generate channel list entry */ outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG); @@ -543,36 +513,29 @@ static int me4000_ai_insn_read(struct comedi_device *dev, outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_TIMER_REG); outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG); - /* Start conversion by dummy read */ - inl(dev->iobase + ME4000_AI_START_REG); + for (i = 0; i < insn->n; i++) { + unsigned int val; - /* Wait until ready */ - udelay(10); - if (!(inl(dev->iobase + ME4000_AI_STATUS_REG) & - ME4000_AI_STATUS_BIT_EF_DATA)) { - dev_err(dev->class_dev, "Value not available after wait\n"); - return -EIO; + /* start conversion by dummy read */ + inl(dev->iobase + ME4000_AI_START_REG); + + ret = comedi_timeout(dev, s, insn, me4000_ai_eoc, 0); + if (ret) + break; + + val = me4000_ai_get_sample(dev, s); + data[i] = comedi_offset_munge(s, val); } - /* Read value from data fifo */ - lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF; - data[0] = lval ^ 0x8000; + me4000_ai_reset(dev); - return 1; + return ret ? ret : insn->n; } static int me4000_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - unsigned int tmp; - - /* Stop any running conversion */ - tmp = inl(dev->iobase + ME4000_AI_CTRL_REG); - tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP); - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); - - /* Clear the control register */ - outl(0x0, dev->iobase + ME4000_AI_CTRL_REG); + me4000_ai_reset(dev); return 0; } @@ -581,8 +544,6 @@ static int me4000_ai_check_chanlist(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - const struct me4000_board *board = dev->board_ptr; - unsigned int max_diff_chan = board->ai_diff_nchan; unsigned int aref0 = CR_AREF(cmd->chanlist[0]); int i; @@ -598,7 +559,13 @@ static int me4000_ai_check_chanlist(struct comedi_device *dev, } if (aref == AREF_DIFF) { - if (chan >= max_diff_chan) { + if (!(s->subdev_flags && SDF_DIFF)) { + dev_err(dev->class_dev, + "Differential inputs are not available\n"); + return -EINVAL; + } + + if (chan >= (s->n_chan / 2)) { dev_dbg(dev->class_dev, "Channel number to high\n"); return -EINVAL; @@ -615,202 +582,127 @@ static int me4000_ai_check_chanlist(struct comedi_device *dev, return 0; } -static int ai_round_cmd_args(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_cmd *cmd, - unsigned int *init_ticks, - unsigned int *scan_ticks, unsigned int *chan_ticks) +static void me4000_ai_round_cmd_args(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) { + struct me4000_private *devpriv = dev->private; int rest; - *init_ticks = 0; - *scan_ticks = 0; - *chan_ticks = 0; + devpriv->ai_init_ticks = 0; + devpriv->ai_scan_ticks = 0; + devpriv->ai_chan_ticks = 0; if (cmd->start_arg) { - *init_ticks = (cmd->start_arg * 33) / 1000; + devpriv->ai_init_ticks = (cmd->start_arg * 33) / 1000; rest = (cmd->start_arg * 33) % 1000; if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_NEAREST) { if (rest > 33) - (*init_ticks)++; + devpriv->ai_init_ticks++; } else if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_UP) { if (rest) - (*init_ticks)++; + devpriv->ai_init_ticks++; } } if (cmd->scan_begin_arg) { - *scan_ticks = (cmd->scan_begin_arg * 33) / 1000; + devpriv->ai_scan_ticks = (cmd->scan_begin_arg * 33) / 1000; rest = (cmd->scan_begin_arg * 33) % 1000; if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_NEAREST) { if (rest > 33) - (*scan_ticks)++; + devpriv->ai_scan_ticks++; } else if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_UP) { if (rest) - (*scan_ticks)++; + devpriv->ai_scan_ticks++; } } if (cmd->convert_arg) { - *chan_ticks = (cmd->convert_arg * 33) / 1000; + devpriv->ai_chan_ticks = (cmd->convert_arg * 33) / 1000; rest = (cmd->convert_arg * 33) % 1000; if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_NEAREST) { if (rest > 33) - (*chan_ticks)++; + devpriv->ai_chan_ticks++; } else if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_UP) { if (rest) - (*chan_ticks)++; + devpriv->ai_chan_ticks++; } } - - return 0; -} - -static void ai_write_timer(struct comedi_device *dev, - unsigned int init_ticks, - unsigned int scan_ticks, unsigned int chan_ticks) -{ - outl(init_ticks - 1, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG); - outl(0x0, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG); - - if (scan_ticks) { - outl(scan_ticks - 1, dev->iobase + ME4000_AI_SCAN_TIMER_LOW_REG); - outl(0x0, dev->iobase + ME4000_AI_SCAN_TIMER_HIGH_REG); - } - - outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG); - outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_TIMER_REG); } -static int ai_write_chanlist(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_cmd *cmd) +static void me4000_ai_write_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) { - unsigned int entry; - unsigned int chan; - unsigned int rang; - unsigned int aref; int i; for (i = 0; i < cmd->chanlist_len; i++) { - chan = CR_CHAN(cmd->chanlist[i]); - rang = CR_RANGE(cmd->chanlist[i]); - aref = CR_AREF(cmd->chanlist[i]); - - entry = chan; + unsigned int chan = CR_CHAN(cmd->chanlist[i]); + unsigned int range = CR_RANGE(cmd->chanlist[i]); + unsigned int aref = CR_AREF(cmd->chanlist[i]); + unsigned int entry; - if (rang == 0) - entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5; - else if (rang == 1) - entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10; - else if (rang == 2) - entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5; - else - entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10; + entry = chan | ME4000_AI_LIST_RANGE(range); if (aref == AREF_DIFF) entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL; - else - entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED; + + if (i == (cmd->chanlist_len - 1)) + entry |= ME4000_AI_LIST_LAST_ENTRY; outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG); } - - return 0; } -static int ai_prepare(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_cmd *cmd, - unsigned int init_ticks, - unsigned int scan_ticks, unsigned int chan_ticks) +static int me4000_ai_do_cmd(struct comedi_device *dev, + struct comedi_subdevice *s) { - unsigned int tmp = 0; + struct me4000_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; + unsigned int ctrl; /* Write timer arguments */ - ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks); + outl(devpriv->ai_init_ticks - 1, + dev->iobase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG); + outl(0x0, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG); + + if (devpriv->ai_scan_ticks) { + outl(devpriv->ai_scan_ticks - 1, + dev->iobase + ME4000_AI_SCAN_TIMER_LOW_REG); + outl(0x0, dev->iobase + ME4000_AI_SCAN_TIMER_HIGH_REG); + } - /* Reset control register */ - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + outl(devpriv->ai_chan_ticks - 1, + dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG); + outl(devpriv->ai_chan_ticks - 1, + dev->iobase + ME4000_AI_CHAN_TIMER_REG); /* Start sources */ - if ((cmd->start_src == TRIG_EXT && - cmd->scan_begin_src == TRIG_TIMER && - cmd->convert_src == TRIG_TIMER) || - (cmd->start_src == TRIG_EXT && - cmd->scan_begin_src == TRIG_FOLLOW && - cmd->convert_src == TRIG_TIMER)) { - tmp = ME4000_AI_CTRL_BIT_MODE_1 | - ME4000_AI_CTRL_BIT_CHANNEL_FIFO | - ME4000_AI_CTRL_BIT_DATA_FIFO; - } else if (cmd->start_src == TRIG_EXT && - cmd->scan_begin_src == TRIG_EXT && - cmd->convert_src == TRIG_TIMER) { - tmp = ME4000_AI_CTRL_BIT_MODE_2 | - ME4000_AI_CTRL_BIT_CHANNEL_FIFO | - ME4000_AI_CTRL_BIT_DATA_FIFO; - } else if (cmd->start_src == TRIG_EXT && - cmd->scan_begin_src == TRIG_EXT && - cmd->convert_src == TRIG_EXT) { - tmp = ME4000_AI_CTRL_BIT_MODE_0 | - ME4000_AI_CTRL_BIT_MODE_1 | - ME4000_AI_CTRL_BIT_CHANNEL_FIFO | - ME4000_AI_CTRL_BIT_DATA_FIFO; - } else { - tmp = ME4000_AI_CTRL_BIT_MODE_0 | - ME4000_AI_CTRL_BIT_CHANNEL_FIFO | - ME4000_AI_CTRL_BIT_DATA_FIFO; - } + ctrl = devpriv->ai_ctrl_mode | + ME4000_AI_CTRL_CHANNEL_FIFO | + ME4000_AI_CTRL_DATA_FIFO; /* Stop triggers */ if (cmd->stop_src == TRIG_COUNT) { outl(cmd->chanlist_len * cmd->stop_arg, dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG); - tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ; + ctrl |= ME4000_AI_CTRL_SC_IRQ; } else if (cmd->stop_src == TRIG_NONE && cmd->scan_end_src == TRIG_COUNT) { outl(cmd->scan_end_arg, dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG); - tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ; - } else { - tmp |= ME4000_AI_CTRL_BIT_HF_IRQ; + ctrl |= ME4000_AI_CTRL_SC_IRQ; } + ctrl |= ME4000_AI_CTRL_HF_IRQ; /* Write the setup to the control register */ - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + outl(ctrl, dev->iobase + ME4000_AI_CTRL_REG); /* Write the channel list */ - ai_write_chanlist(dev, s, cmd); - - return 0; -} - -static int me4000_ai_do_cmd(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - int err; - unsigned int init_ticks = 0; - unsigned int scan_ticks = 0; - unsigned int chan_ticks = 0; - struct comedi_cmd *cmd = &s->async->cmd; - - /* Reset the analog input */ - err = me4000_ai_cancel(dev, s); - if (err) - return err; - - /* Round the timer arguments */ - err = ai_round_cmd_args(dev, - s, cmd, &init_ticks, &scan_ticks, &chan_ticks); - if (err) - return err; - - /* Prepare the AI for acquisition */ - err = ai_prepare(dev, s, cmd, init_ticks, scan_ticks, chan_ticks); - if (err) - return err; + me4000_ai_write_chanlist(dev, s, cmd); /* Start acquistion by dummy read */ inl(dev->iobase + ME4000_AI_START_REG); @@ -822,14 +714,9 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - unsigned int init_ticks; - unsigned int chan_ticks; - unsigned int scan_ticks; + struct me4000_private *devpriv = dev->private; int err = 0; - /* Round the timer arguments */ - ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks); - /* Step 1 : check if triggers are trivially valid */ err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); @@ -857,21 +744,28 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, if (cmd->start_src == TRIG_NOW && cmd->scan_begin_src == TRIG_TIMER && cmd->convert_src == TRIG_TIMER) { + devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_0; } else if (cmd->start_src == TRIG_NOW && cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_TIMER) { + devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_0; } else if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_TIMER && cmd->convert_src == TRIG_TIMER) { + devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_1; } else if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_TIMER) { + devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_1; } else if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT && cmd->convert_src == TRIG_TIMER) { + devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_2; } else if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT && cmd->convert_src == TRIG_EXT) { + devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_0 | + ME4000_AI_CTRL_MODE_1; } else { err |= -EINVAL; } @@ -887,15 +781,19 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, cmd->chanlist_len = 1; err |= -EINVAL; } - if (init_ticks < 66) { + + /* Round the timer arguments */ + me4000_ai_round_cmd_args(dev, s, cmd); + + if (devpriv->ai_init_ticks < 66) { cmd->start_arg = 2000; err |= -EINVAL; } - if (scan_ticks && scan_ticks < 67) { + if (devpriv->ai_scan_ticks && devpriv->ai_scan_ticks < 67) { cmd->scan_begin_arg = 2031; err |= -EINVAL; } - if (chan_ticks < 66) { + if (devpriv->ai_chan_ticks < 66) { cmd->convert_arg = 2000; err |= -EINVAL; } @@ -915,17 +813,18 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, cmd->scan_begin_src == TRIG_TIMER && cmd->convert_src == TRIG_TIMER) { /* Check timer arguments */ - if (init_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid start arg\n"); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } - if (chan_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid convert arg\n"); cmd->convert_arg = 2000; /* 66 ticks at least */ err++; } - if (scan_ticks <= cmd->chanlist_len * chan_ticks) { + if (devpriv->ai_scan_ticks <= + cmd->chanlist_len * devpriv->ai_chan_ticks) { dev_err(dev->class_dev, "Invalid scan end arg\n"); /* At least one tick more */ @@ -936,12 +835,12 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_TIMER) { /* Check timer arguments */ - if (init_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid start arg\n"); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } - if (chan_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid convert arg\n"); cmd->convert_arg = 2000; /* 66 ticks at least */ err++; @@ -950,17 +849,18 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, cmd->scan_begin_src == TRIG_TIMER && cmd->convert_src == TRIG_TIMER) { /* Check timer arguments */ - if (init_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid start arg\n"); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } - if (chan_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid convert arg\n"); cmd->convert_arg = 2000; /* 66 ticks at least */ err++; } - if (scan_ticks <= cmd->chanlist_len * chan_ticks) { + if (devpriv->ai_scan_ticks <= + cmd->chanlist_len * devpriv->ai_chan_ticks) { dev_err(dev->class_dev, "Invalid scan end arg\n"); /* At least one tick more */ @@ -971,12 +871,12 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_TIMER) { /* Check timer arguments */ - if (init_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid start arg\n"); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } - if (chan_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid convert arg\n"); cmd->convert_arg = 2000; /* 66 ticks at least */ err++; @@ -985,12 +885,12 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, cmd->scan_begin_src == TRIG_EXT && cmd->convert_src == TRIG_TIMER) { /* Check timer arguments */ - if (init_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid start arg\n"); cmd->start_arg = 2000; /* 66 ticks at least */ err++; } - if (chan_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid convert arg\n"); cmd->convert_arg = 2000; /* 66 ticks at least */ err++; @@ -999,7 +899,7 @@ static int me4000_ai_do_cmd_test(struct comedi_device *dev, cmd->scan_begin_src == TRIG_EXT && cmd->convert_src == TRIG_EXT) { /* Check timer arguments */ - if (init_ticks < ME4000_AI_MIN_TICKS) { + if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) { dev_err(dev->class_dev, "Invalid start arg\n"); cmd->start_arg = 2000; /* 66 ticks at least */ err++; @@ -1039,103 +939,57 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) return IRQ_NONE; if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) & - ME4000_IRQ_STATUS_BIT_AI_HF) { + ME4000_IRQ_STATUS_AI_HF) { /* Read status register to find out what happened */ - tmp = inl(dev->iobase + ME4000_AI_CTRL_REG); - - if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) && - !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) && - (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) { - c = ME4000_AI_FIFO_COUNT; - - /* - * FIFO overflow, so stop conversion - * and disable all interrupts - */ - tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; - tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | - ME4000_AI_CTRL_BIT_SC_IRQ); - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); - - s->async->events |= COMEDI_CB_ERROR; + tmp = inl(dev->iobase + ME4000_AI_STATUS_REG); + if (!(tmp & ME4000_AI_STATUS_FF_DATA) && + !(tmp & ME4000_AI_STATUS_HF_DATA) && + (tmp & ME4000_AI_STATUS_EF_DATA)) { dev_err(dev->class_dev, "FIFO overflow\n"); - } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA) - && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) - && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) { + s->async->events |= COMEDI_CB_ERROR; + c = ME4000_AI_FIFO_COUNT; + } else if ((tmp & ME4000_AI_STATUS_FF_DATA) && + !(tmp & ME4000_AI_STATUS_HF_DATA) && + (tmp & ME4000_AI_STATUS_EF_DATA)) { c = ME4000_AI_FIFO_COUNT / 2; } else { - dev_err(dev->class_dev, - "Can't determine state of fifo\n"); - c = 0; - - /* - * Undefined state, so stop conversion - * and disable all interrupts - */ - tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; - tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | - ME4000_AI_CTRL_BIT_SC_IRQ); - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); - - s->async->events |= COMEDI_CB_ERROR; - dev_err(dev->class_dev, "Undefined FIFO state\n"); + s->async->events |= COMEDI_CB_ERROR; + c = 0; } for (i = 0; i < c; i++) { - /* Read value from data fifo */ - lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF; - lval ^= 0x8000; - - if (!comedi_buf_write_samples(s, &lval, 1)) { - /* - * Buffer overflow, so stop conversion - * and disable all interrupts - */ - tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; - tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | - ME4000_AI_CTRL_BIT_SC_IRQ); - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); + lval = me4000_ai_get_sample(dev, s); + if (!comedi_buf_write_samples(s, &lval, 1)) break; - } } /* Work is done, so reset the interrupt */ - tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET; + tmp |= ME4000_AI_CTRL_HF_IRQ_RESET; outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); - tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET; + tmp &= ~ME4000_AI_CTRL_HF_IRQ_RESET; outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); } if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) & - ME4000_IRQ_STATUS_BIT_SC) { + ME4000_IRQ_STATUS_SC) { + /* Acquisition is complete */ s->async->events |= COMEDI_CB_EOA; - /* - * Acquisition is complete, so stop - * conversion and disable all interrupts - */ - tmp = inl(dev->iobase + ME4000_AI_CTRL_REG); - tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP; - tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ); - outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); - /* Poll data until fifo empty */ - while (inl(dev->iobase + ME4000_AI_CTRL_REG) & - ME4000_AI_STATUS_BIT_EF_DATA) { - /* Read value from data fifo */ - lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF; - lval ^= 0x8000; - + while (inl(dev->iobase + ME4000_AI_STATUS_REG) & + ME4000_AI_STATUS_EF_DATA) { + lval = me4000_ai_get_sample(dev, s); if (!comedi_buf_write_samples(s, &lval, 1)) break; } /* Work is done, so reset the interrupt */ - tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET; + tmp = inl(dev->iobase + ME4000_AI_CTRL_REG); + tmp |= ME4000_AI_CTRL_SC_IRQ_RESET; outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); - tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET; + tmp &= ~ME4000_AI_CTRL_SC_IRQ_RESET; outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); } @@ -1149,12 +1003,12 @@ static int me4000_ao_insn_write(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - int chan = CR_CHAN(insn->chanspec); + unsigned int chan = CR_CHAN(insn->chanspec); unsigned int tmp; /* Stop any running conversion */ tmp = inl(dev->iobase + ME4000_AO_CTRL_REG(chan)); - tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP; + tmp |= ME4000_AO_CTRL_IMMEDIATE_STOP; outl(tmp, dev->iobase + ME4000_AO_CTRL_REG(chan)); /* Clear control register and set to single mode */ @@ -1217,18 +1071,18 @@ static int me4000_dio_insn_config(struct comedi_device *dev, return ret; tmp = inl(dev->iobase + ME4000_DIO_CTRL_REG); - tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 | ME4000_DIO_CTRL_BIT_MODE_1 | - ME4000_DIO_CTRL_BIT_MODE_2 | ME4000_DIO_CTRL_BIT_MODE_3 | - ME4000_DIO_CTRL_BIT_MODE_4 | ME4000_DIO_CTRL_BIT_MODE_5 | - ME4000_DIO_CTRL_BIT_MODE_6 | ME4000_DIO_CTRL_BIT_MODE_7); + tmp &= ~(ME4000_DIO_CTRL_MODE_0 | ME4000_DIO_CTRL_MODE_1 | + ME4000_DIO_CTRL_MODE_2 | ME4000_DIO_CTRL_MODE_3 | + ME4000_DIO_CTRL_MODE_4 | ME4000_DIO_CTRL_MODE_5 | + ME4000_DIO_CTRL_MODE_6 | ME4000_DIO_CTRL_MODE_7); if (s->io_bits & 0x000000ff) - tmp |= ME4000_DIO_CTRL_BIT_MODE_0; + tmp |= ME4000_DIO_CTRL_MODE_0; if (s->io_bits & 0x0000ff00) - tmp |= ME4000_DIO_CTRL_BIT_MODE_2; + tmp |= ME4000_DIO_CTRL_MODE_2; if (s->io_bits & 0x00ff0000) - tmp |= ME4000_DIO_CTRL_BIT_MODE_4; + tmp |= ME4000_DIO_CTRL_MODE_4; if (s->io_bits & 0xff000000) - tmp |= ME4000_DIO_CTRL_BIT_MODE_6; + tmp |= ME4000_DIO_CTRL_MODE_6; /* * Check for optoisolated ME-4000 version. @@ -1238,9 +1092,8 @@ static int me4000_dio_insn_config(struct comedi_device *dev, if (inl(dev->iobase + ME4000_DIO_DIR_REG)) { s->io_bits |= 0x000000ff; s->io_bits &= ~0x0000ff00; - tmp |= ME4000_DIO_CTRL_BIT_MODE_0; - tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 | - ME4000_DIO_CTRL_BIT_MODE_3); + tmp |= ME4000_DIO_CTRL_MODE_0; + tmp &= ~(ME4000_DIO_CTRL_MODE_2 | ME4000_DIO_CTRL_MODE_3); } outl(tmp, dev->iobase + ME4000_DIO_CTRL_REG); @@ -1253,7 +1106,7 @@ static int me4000_auto_attach(struct comedi_device *dev, { struct pci_dev *pcidev = comedi_to_pci_dev(dev); const struct me4000_board *board = NULL; - struct me4000_info *info; + struct me4000_private *devpriv; struct comedi_subdevice *s; int result; @@ -1264,17 +1117,17 @@ static int me4000_auto_attach(struct comedi_device *dev, dev->board_ptr = board; dev->board_name = board->name; - info = comedi_alloc_devpriv(dev, sizeof(*info)); - if (!info) + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); + if (!devpriv) return -ENOMEM; result = comedi_pci_enable(dev); if (result) return result; - info->plx_regbase = pci_resource_start(pcidev, 1); + devpriv->plx_regbase = pci_resource_start(pcidev, 1); dev->iobase = pci_resource_start(pcidev, 2); - if (!info->plx_regbase || !dev->iobase) + if (!devpriv->plx_regbase || !dev->iobase) return -ENODEV; result = comedi_load_firmware(dev, &pcidev->dev, ME4000_FIRMWARE, @@ -1287,79 +1140,66 @@ static int me4000_auto_attach(struct comedi_device *dev, if (pcidev->irq > 0) { result = request_irq(pcidev->irq, me4000_ai_isr, IRQF_SHARED, dev->board_name, dev); - if (result == 0) + if (result == 0) { dev->irq = pcidev->irq; + + /* Enable interrupts on the PLX */ + outl(PLX9052_INTCSR_LI1ENAB | PLX9052_INTCSR_LI1POL | + PLX9052_INTCSR_PCIENAB, + devpriv->plx_regbase + PLX9052_INTCSR); + } } result = comedi_alloc_subdevices(dev, 4); if (result) return result; - /*========================================================================= - Analog input subdevice - ========================================================================*/ - + /* Analog Input subdevice */ s = &dev->subdevices[0]; - - if (board->ai_nchan) { - s->type = COMEDI_SUBD_AI; - s->subdev_flags = - SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; - s->n_chan = board->ai_nchan; - s->maxdata = 0xFFFF; /* 16 bit ADC */ - s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT; - s->range_table = &me4000_ai_range; - s->insn_read = me4000_ai_insn_read; - - if (dev->irq) { - dev->read_subdev = s; - s->subdev_flags |= SDF_CMD_READ; - s->cancel = me4000_ai_cancel; - s->do_cmdtest = me4000_ai_do_cmd_test; - s->do_cmd = me4000_ai_do_cmd; - } - } else { - s->type = COMEDI_SUBD_UNUSED; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND; + if (board->can_do_diff_ai) + s->subdev_flags |= SDF_DIFF; + s->n_chan = board->ai_nchan; + s->maxdata = 0xffff; + s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT; + s->range_table = &me4000_ai_range; + s->insn_read = me4000_ai_insn_read; + + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->cancel = me4000_ai_cancel; + s->do_cmdtest = me4000_ai_do_cmd_test; + s->do_cmd = me4000_ai_do_cmd; } - /*========================================================================= - Analog output subdevice - ========================================================================*/ - + /* Analog Output subdevice */ s = &dev->subdevices[1]; - - if (board->ao_nchan) { - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE | SDF_COMMON | SDF_GROUND; - s->n_chan = board->ao_nchan; - s->maxdata = 0xFFFF; /* 16 bit DAC */ - s->range_table = &range_bipolar10; - s->insn_write = me4000_ao_insn_write; + if (board->has_ao) { + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_COMMON | SDF_GROUND; + s->n_chan = 4; + s->maxdata = 0xffff; + s->range_table = &range_bipolar10; + s->insn_write = me4000_ao_insn_write; result = comedi_alloc_subdev_readback(s); if (result) return result; } else { - s->type = COMEDI_SUBD_UNUSED; + s->type = COMEDI_SUBD_UNUSED; } - /*========================================================================= - Digital I/O subdevice - ========================================================================*/ - + /* Digital I/O subdevice */ s = &dev->subdevices[2]; - - if (board->dio_nchan) { - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = board->dio_nchan; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = me4000_dio_insn_bits; - s->insn_config = me4000_dio_insn_config; - } else { - s->type = COMEDI_SUBD_UNUSED; - } + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 32; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = me4000_dio_insn_bits; + s->insn_config = me4000_dio_insn_config; /* * Check for optoisolated ME-4000 version. If one the first @@ -1367,7 +1207,7 @@ static int me4000_auto_attach(struct comedi_device *dev, */ if (!inl(dev->iobase + ME4000_DIO_DIR_REG)) { s->io_bits |= 0xFF; - outl(ME4000_DIO_CTRL_BIT_MODE_0, + outl(ME4000_DIO_CTRL_MODE_0, dev->iobase + ME4000_DIO_DIR_REG); } @@ -1393,8 +1233,12 @@ static int me4000_auto_attach(struct comedi_device *dev, static void me4000_detach(struct comedi_device *dev) { - if (dev->iobase) - me4000_reset(dev); + if (dev->irq) { + struct me4000_private *devpriv = dev->private; + + /* Disable interrupts on the PLX */ + outl(0, devpriv->plx_regbase + PLX9052_INTCSR); + } comedi_pci_detach(dev); } @@ -1438,6 +1282,6 @@ static struct pci_driver me4000_pci_driver = { module_comedi_pci_driver(me4000_driver, me4000_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for Meilhaus ME-4000 series boards"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(ME4000_FIRMWARE); diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 781b321587dc..a353d1b155bb 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -305,7 +305,7 @@ static int check_channel_list(struct comedi_device *dev, chansegment[0] = chanlist[0]; for (i = 1, seglen = 1; i < chanlen; i++, seglen++) { /* we detect loop, this must by finish */ - if (chanlist[0] == chanlist[i]) + if (chanlist[0] == chanlist[i]) break; nowmustbechan = (CR_CHAN(chansegment[i - 1]) + 1) % chanlen; diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index eaa9add491df..649cf47184a4 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -1,6 +1,6 @@ /* * usbduxsigma.c - * Copyright (C) 2011-2014 Bernd Porr, mail@berndporr.me.uk + * Copyright (C) 2011-2015 Bernd Porr, mail@berndporr.me.uk * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,7 +18,7 @@ * Description: University of Stirling USB DAQ & INCITE Technology Limited * Devices: [ITL] USB-DUX-SIGMA (usbduxsigma) * Author: Bernd Porr <mail@berndporr.me.uk> - * Updated: 10 Oct 2014 + * Updated: 20 July 2015 * Status: stable */ @@ -39,6 +39,7 @@ * 0.4: fixed D/A voltage range * 0.5: various bug fixes, health check at startup * 0.6: corrected wrong input range + * 0.7: rewrite code that urb->interval is always 1 */ #include <linux/kernel.h> @@ -122,7 +123,7 @@ #define RETRIES 10 /* bulk transfer commands to usbduxsigma */ -#define USBBUXSIGMA_AD_CMD 0 +#define USBBUXSIGMA_AD_CMD 9 #define USBDUXSIGMA_DA_CMD 1 #define USBDUXSIGMA_DIO_CFG_CMD 2 #define USBDUXSIGMA_DIO_BITS_CMD 3 @@ -217,24 +218,28 @@ static void usbduxsigma_ai_handle_urb(struct comedi_device *dev, int ret; int i; - devpriv->ai_counter--; - if (devpriv->ai_counter == 0) { - devpriv->ai_counter = devpriv->ai_timer; - - /* get the data from the USB bus and hand it over to comedi */ - for (i = 0; i < cmd->chanlist_len; i++) { - /* transfer data, note first byte is the DIO state */ - val = be32_to_cpu(devpriv->in_buf[i+1]); - val &= 0x00ffffff; /* strip status byte */ - val ^= 0x00800000; /* convert to unsigned */ + if ((urb->actual_length > 0) && (urb->status != -EXDEV)) { + devpriv->ai_counter--; + if (devpriv->ai_counter == 0) { + devpriv->ai_counter = devpriv->ai_timer; + + /* get the data from the USB bus + and hand it over to comedi */ + for (i = 0; i < cmd->chanlist_len; i++) { + /* transfer data, + note first byte is the DIO state */ + val = be32_to_cpu(devpriv->in_buf[i+1]); + val &= 0x00ffffff; /* strip status byte */ + val ^= 0x00800000; /* convert to unsigned */ + + if (!comedi_buf_write_samples(s, &val, 1)) + return; + } - if (!comedi_buf_write_samples(s, &val, 1)) - return; + if (cmd->stop_src == TRIG_COUNT && + async->scans_done >= cmd->stop_arg) + async->events |= COMEDI_CB_EOA; } - - if (cmd->stop_src == TRIG_COUNT && - async->scans_done >= cmd->stop_arg) - async->events |= COMEDI_CB_EOA; } /* if command is still running, resubmit urb */ @@ -374,10 +379,7 @@ static void usbduxsigma_ao_handle_urb(struct comedi_device *dev, urb->transfer_buffer_length = SIZEOUTBUF; urb->dev = comedi_to_usb_dev(dev); urb->status = 0; - if (devpriv->high_speed) - urb->interval = 8; /* uframes */ - else - urb->interval = 1; /* frames */ + urb->interval = 1; /* (u)frames */ urb->number_of_packets = 1; urb->iso_frame_desc[0].offset = 0; urb->iso_frame_desc[0].length = SIZEOUTBUF; @@ -441,7 +443,6 @@ static int usbduxsigma_submit_urbs(struct comedi_device *dev, int input_urb) { struct usb_device *usb = comedi_to_usb_dev(dev); - struct usbduxsigma_private *devpriv = dev->private; struct urb *urb; int ret; int i; @@ -452,7 +453,7 @@ static int usbduxsigma_submit_urbs(struct comedi_device *dev, /* in case of a resubmission after an unlink... */ if (input_urb) - urb->interval = devpriv->ai_interval; + urb->interval = 1; urb->context = dev; urb->dev = usb; urb->status = 0; @@ -481,6 +482,7 @@ static int usbduxsigma_ai_cmdtest(struct comedi_device *dev, struct usbduxsigma_private *devpriv = dev->private; int high_speed = devpriv->high_speed; int interval = usbduxsigma_chans_to_interval(cmd->chanlist_len); + unsigned int tmp; int err = 0; /* Step 1 : check if triggers are trivially valid */ @@ -508,35 +510,20 @@ static int usbduxsigma_ai_cmdtest(struct comedi_device *dev, err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); - if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */ - err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0); - - if (cmd->scan_begin_src == TRIG_TIMER) { - unsigned int tmp; - - if (high_speed) { - /* - * In high speed mode microframes are possible. - * However, during one microframe we can roughly - * sample two channels. Thus, the more channels - * are in the channel list the more time we need. - */ - err |= comedi_check_trigger_arg_min(&cmd-> - scan_begin_arg, - (1000000 / 8 * - interval)); - - tmp = (cmd->scan_begin_arg / 125000) * 125000; - } else { - /* full speed */ - /* 1kHz scans every USB frame */ - err |= comedi_check_trigger_arg_min(&cmd-> - scan_begin_arg, - 1000000); - - tmp = (cmd->scan_begin_arg / 1000000) * 1000000; - } - err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, tmp); + if (high_speed) { + /* + * In high speed mode microframes are possible. + * However, during one microframe we can roughly + * sample two channels. Thus, the more channels + * are in the channel list the more time we need. + */ + err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, + (125000 * interval)); + } else { + /* full speed */ + /* 1kHz scans every USB frame */ + err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, + 1000000); } err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, @@ -552,21 +539,8 @@ static int usbduxsigma_ai_cmdtest(struct comedi_device *dev, /* Step 4: fix up any arguments */ - if (high_speed) { - /* - * every 2 channels get a time window of 125us. Thus, if we - * sample all 16 channels we need 1ms. If we sample only one - * channel we need only 125us - */ - devpriv->ai_interval = interval; - devpriv->ai_timer = cmd->scan_begin_arg / (125000 * interval); - } else { - /* interval always 1ms */ - devpriv->ai_interval = 1; - devpriv->ai_timer = cmd->scan_begin_arg / 1000000; - } - if (devpriv->ai_timer < 1) - err |= -EINVAL; + tmp = rounddown(cmd->scan_begin_arg, high_speed ? 125000 : 1000000); + err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, tmp); if (err) return 4; @@ -668,19 +642,36 @@ static int usbduxsigma_ai_cmd(struct comedi_device *dev, down(&devpriv->sem); + if (devpriv->high_speed) { + /* + * every 2 channels get a time window of 125us. Thus, if we + * sample all 16 channels we need 1ms. If we sample only one + * channel we need only 125us + */ + unsigned int interval = usbduxsigma_chans_to_interval(len); + + devpriv->ai_interval = interval; + devpriv->ai_timer = cmd->scan_begin_arg / (125000 * interval); + } else { + /* interval always 1ms */ + devpriv->ai_interval = 1; + devpriv->ai_timer = cmd->scan_begin_arg / 1000000; + } + for (i = 0; i < len; i++) { unsigned int chan = CR_CHAN(cmd->chanlist[i]); create_adc_command(chan, &muxsg0, &muxsg1); } - devpriv->dux_commands[1] = len; /* num channels per time step */ - devpriv->dux_commands[2] = 0x12; /* CONFIG0 */ - devpriv->dux_commands[3] = 0x03; /* CONFIG1: 23kHz sample, delay 0us */ - devpriv->dux_commands[4] = 0x00; /* CONFIG3: diff. channels off */ - devpriv->dux_commands[5] = muxsg0; - devpriv->dux_commands[6] = muxsg1; - devpriv->dux_commands[7] = sysred; + devpriv->dux_commands[1] = devpriv->ai_interval; + devpriv->dux_commands[2] = len; /* num channels per time step */ + devpriv->dux_commands[3] = 0x12; /* CONFIG0 */ + devpriv->dux_commands[4] = 0x03; /* CONFIG1: 23kHz sample, delay 0us */ + devpriv->dux_commands[5] = 0x00; /* CONFIG3: diff. channels off */ + devpriv->dux_commands[6] = muxsg0; + devpriv->dux_commands[7] = muxsg1; + devpriv->dux_commands[8] = sysred; ret = usbbuxsigma_send_cmd(dev, USBBUXSIGMA_AD_CMD); if (ret < 0) { @@ -848,29 +839,22 @@ static int usbduxsigma_ao_cmdtest(struct comedi_device *dev, struct comedi_cmd *cmd) { struct usbduxsigma_private *devpriv = dev->private; + unsigned int tmp; int err = 0; - int high_speed; - unsigned int flags; - - /* high speed conversions are not used yet */ - high_speed = 0; /* (devpriv->high_speed) */ /* Step 1 : check if triggers are trivially valid */ err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); - if (high_speed) { - /* - * start immediately a new scan - * the sampling rate is set by the coversion rate - */ - flags = TRIG_FOLLOW; - } else { - /* start a new scan (output at once) with a timer */ - flags = TRIG_TIMER; - } - err |= comedi_check_trigger_src(&cmd->scan_begin_src, flags); - + /* + * For now, always use "scan" timing with all channels updated at once + * (cmd->scan_begin_src == TRIG_TIMER, cmd->convert_src == TRIG_NOW). + * + * In a future version, "convert" timing with channels updated + * indivually may be supported in high speed mode + * (cmd->scan_begin_src == TRIG_FOLLOW, cmd->convert_src == TRIG_TIMER). + */ + err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER); err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW); err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); @@ -894,17 +878,7 @@ static int usbduxsigma_ao_cmdtest(struct comedi_device *dev, err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); - if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */ - err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0); - - if (cmd->scan_begin_src == TRIG_TIMER) { - err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, - 1000000); - } - - /* not used now, is for later use */ - if (cmd->convert_src == TRIG_TIMER) - err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 125000); + err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, 1000000); err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); @@ -919,19 +893,8 @@ static int usbduxsigma_ao_cmdtest(struct comedi_device *dev, /* Step 4: fix up any arguments */ - /* we count in timer steps */ - if (high_speed) { - /* timing of the conversion itself: every 125 us */ - devpriv->ao_timer = cmd->convert_arg / 125000; - } else { - /* - * timing of the scan: every 1ms - * we get all channels at once - */ - devpriv->ao_timer = cmd->scan_begin_arg / 1000000; - } - if (devpriv->ao_timer < 1) - err |= -EINVAL; + tmp = rounddown(cmd->scan_begin_arg, 1000000); + err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, tmp); if (err) return 4; @@ -948,6 +911,14 @@ static int usbduxsigma_ao_cmd(struct comedi_device *dev, down(&devpriv->sem); + /* + * For now, only "scan" timing is supported. A future version may + * support "convert" timing in high speed mode. + * + * Timing of the scan: every 1ms all channels updated at once. + */ + devpriv->ao_timer = cmd->scan_begin_arg / 1000000; + devpriv->ao_counter = devpriv->ao_timer; if (cmd->start_src == TRIG_NOW) { @@ -1427,10 +1398,7 @@ static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev) urb->transfer_buffer_length = SIZEOUTBUF; urb->iso_frame_desc[0].offset = 0; urb->iso_frame_desc[0].length = SIZEOUTBUF; - if (devpriv->high_speed) - urb->interval = 8; /* uframes */ - else - urb->interval = 1; /* frames */ + urb->interval = 1; /* (u)frames */ } if (devpriv->pwm_buf_sz) { @@ -1653,7 +1621,7 @@ static struct usb_driver usbduxsigma_usb_driver = { }; module_comedi_usb_driver(usbduxsigma_driver, usbduxsigma_usb_driver); -MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com"); -MODULE_DESCRIPTION("Stirling/ITL USB-DUX SIGMA -- Bernd.Porr@f2s.com"); +MODULE_AUTHOR("Bernd Porr, mail@berndporr.me.uk"); +MODULE_DESCRIPTION("Stirling/ITL USB-DUX SIGMA -- mail@berndporr.me.uk"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(FIRMWARE); diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c index 6a393b24bdd9..ce3a58a7a171 100644 --- a/drivers/staging/comedi/range.c +++ b/drivers/staging/comedi/range.c @@ -102,7 +102,18 @@ int do_rangeinfo_ioctl(struct comedi_device *dev, * @s: comedi_subdevice struct * @n: number of elements in the chanlist * @chanlist: the chanlist to validate -*/ + * + * Each element consists of a channel number, a range index, an analog + * reference type and some flags, all packed into an unsigned int. + * + * This checks that the channel number and range index are supported by + * the comedi subdevice. It does not check whether the analog reference + * type and the flags are supported. Drivers that care should check those + * themselves. + * + * Return: %0 if all @chanlist elements are valid (success), + * %-EINVAL if one or more elements are invalid. + */ int comedi_check_chanlist(struct comedi_subdevice *s, int n, unsigned int *chanlist) { diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c index b344e035b0ef..9112dd2bf4d7 100644 --- a/drivers/staging/dgap/dgap.c +++ b/drivers/staging/dgap/dgap.c @@ -4953,9 +4953,8 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd, spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - rc = put_user(C_CLOCAL(tty) ? 1 : 0, + return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) arg); - return rc; case TIOCSSOFTCAR: spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h index d04671fa4b75..06ece5151fe4 100644 --- a/drivers/staging/dgnc/dgnc_driver.h +++ b/drivers/staging/dgnc/dgnc_driver.h @@ -21,9 +21,9 @@ #ifndef __DGNC_DRIVER_H #define __DGNC_DRIVER_H -#include <linux/types.h> /* To pick up the varions Linux types */ -#include <linux/tty.h> /* To pick up the various tty structs/defines */ -#include <linux/interrupt.h> /* For irqreturn_t type */ +#include <linux/types.h> +#include <linux/tty.h> +#include <linux/interrupt.h> #include "digi.h" /* Digi specific ioctl header */ #include "dgnc_sysfs.h" /* Support for SYSFS */ diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index f7e68fdd9904..d473010fa474 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -1,6 +1,7 @@ menuconfig FB_TFT tristate "Support for small TFT LCD display modules" - depends on FB && SPI && GPIOLIB + depends on FB && SPI + depends on GPIOLIB || COMPILE_TEST select FB_SYS_FILLRECT select FB_SYS_COPYAREA select FB_SYS_IMAGEBLIT diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c index f04128fb0693..23392eb6799e 100644 --- a/drivers/staging/fbtft/fbtft-core.c +++ b/drivers/staging/fbtft/fbtft-core.c @@ -677,13 +677,13 @@ static void fbtft_merge_fbtftops(struct fbtft_ops *dst, struct fbtft_ops *src) * */ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display, - struct device *dev) + struct device *dev, + struct fbtft_platform_data *pdata) { struct fb_info *info; struct fbtft_par *par; struct fb_ops *fbops = NULL; struct fb_deferred_io *fbdefio = NULL; - struct fbtft_platform_data *pdata = dev->platform_data; u8 *vmem = NULL; void *txbuf = NULL; void *buf = NULL; @@ -828,7 +828,7 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display, par = info->par; par->info = info; - par->pdata = dev->platform_data; + par->pdata = pdata; par->debug = display->debug; par->buf = buf; spin_lock_init(&par->dirty_lock); @@ -1265,12 +1265,11 @@ EXPORT_SYMBOL(fbtft_init_display); */ static int fbtft_verify_gpios(struct fbtft_par *par) { - struct fbtft_platform_data *pdata; + struct fbtft_platform_data *pdata = par->pdata; int i; fbtft_par_dbg(DEBUG_VERIFY_GPIOS, par, "%s()\n", __func__); - pdata = par->info->device->platform_data; if (pdata->display.buswidth != 9 && par->startbyte == 0 && par->gpio.dc < 0) { dev_err(par->info->device, @@ -1388,10 +1387,9 @@ int fbtft_probe_common(struct fbtft_display *display, pdata = fbtft_probe_dt(dev); if (IS_ERR(pdata)) return PTR_ERR(pdata); - dev->platform_data = pdata; } - info = fbtft_framebuffer_alloc(display, dev); + info = fbtft_framebuffer_alloc(display, dev, pdata); if (!info) return -ENOMEM; diff --git a/drivers/staging/fbtft/fbtft.h b/drivers/staging/fbtft/fbtft.h index 7d817eb26eab..ab4a65818786 100644 --- a/drivers/staging/fbtft/fbtft.h +++ b/drivers/staging/fbtft/fbtft.h @@ -264,8 +264,9 @@ struct fbtft_par { /* fbtft-core.c */ extern void fbtft_dbg_hex(const struct device *dev, int groupsize, void *buf, size_t len, const char *fmt, ...); -extern struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display, - struct device *dev); +struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display, + struct device *dev, + struct fbtft_platform_data *pdata); extern void fbtft_framebuffer_release(struct fb_info *info); extern int fbtft_register_framebuffer(struct fb_info *fb_info); extern int fbtft_unregister_framebuffer(struct fb_info *fb_info); diff --git a/drivers/staging/fbtft/flexfb.c b/drivers/staging/fbtft/flexfb.c index ce6e3ae30a2e..c763efc5de7d 100644 --- a/drivers/staging/fbtft/flexfb.c +++ b/drivers/staging/fbtft/flexfb.c @@ -126,6 +126,109 @@ static int ssd1351_init[] = { -1, 0xfd, 0x12, -1, 0xfd, 0xb1, -1, 0xae, -1, 0xb3 -1, 0xab, 0x01, -1, 0xb1, 0x32, -1, 0xb4, 0xa0, 0xb5, 0x55, -1, 0xbb, 0x17, -1, 0xbe, 0x05, -1, 0xc1, 0xc8, 0x80, 0xc8, -1, 0xc7, 0x0f, -1, 0xb6, 0x01, -1, 0xa6, -1, 0xaf, -3 }; +/** + * struct flexfb_lcd_controller - Describes the LCD controller properties + * @name: Model name of the chip + * @width: Width of display in pixels + * @height: Height of display in pixels + * @setaddrwin: Which set_addr_win() implementation to use + * @regwidth: LCD Controller Register width in bits + * @init_seq: LCD initialization sequence + * @init_seq_sz: Size of LCD initialization sequence + */ +struct flexfb_lcd_controller { + const char *name; + unsigned int width; + unsigned int height; + unsigned int setaddrwin; + unsigned int regwidth; + int *init_seq; + int init_seq_sz; +}; + +static const struct flexfb_lcd_controller flexfb_chip_table[] = { + { + .name = "st7735r", + .width = 120, + .height = 160, + .init_seq = st7735r_init, + .init_seq_sz = ARRAY_SIZE(st7735r_init), + }, + { + .name = "hx8340bn", + .width = 176, + .height = 220, + .init_seq = hx8340bn_init, + .init_seq_sz = ARRAY_SIZE(hx8340bn_init), + }, + { + .name = "ili9225", + .width = 176, + .height = 220, + .regwidth = 16, + .init_seq = ili9225_init, + .init_seq_sz = ARRAY_SIZE(ili9225_init), + }, + { + .name = "ili9225", + .width = 176, + .height = 220, + .regwidth = 16, + .init_seq = ili9225_init, + .init_seq_sz = ARRAY_SIZE(ili9225_init), + }, + { + .name = "ili9225", + .width = 176, + .height = 220, + .regwidth = 16, + .init_seq = ili9225_init, + .init_seq_sz = ARRAY_SIZE(ili9225_init), + }, + { + .name = "ili9320", + .width = 240, + .height = 320, + .setaddrwin = 1, + .regwidth = 16, + .init_seq = ili9320_init, + .init_seq_sz = ARRAY_SIZE(ili9320_init), + }, + { + .name = "ili9325", + .width = 240, + .height = 320, + .setaddrwin = 1, + .regwidth = 16, + .init_seq = ili9325_init, + .init_seq_sz = ARRAY_SIZE(ili9325_init), + }, + { + .name = "ili9341", + .width = 240, + .height = 320, + .init_seq = ili9341_init, + .init_seq_sz = ARRAY_SIZE(ili9341_init), + }, + { + .name = "ssd1289", + .width = 240, + .height = 320, + .setaddrwin = 2, + .regwidth = 16, + .init_seq = ssd1289_init, + .init_seq_sz = ARRAY_SIZE(ssd1289_init), + }, + { + .name = "ssd1351", + .width = 128, + .height = 128, + .setaddrwin = 3, + .init_seq = ssd1351_init, + .init_seq_sz = ARRAY_SIZE(ssd1351_init), + }, +}; + /* ili9320, ili9325 */ static void flexfb_set_addr_win_1(struct fbtft_par *par, int xs, int ys, int xe, int ye) @@ -247,8 +350,38 @@ static int flexfb_verify_gpios_db(struct fbtft_par *par) return 0; } +static void flexfb_chip_load_param(const struct flexfb_lcd_controller *chip) +{ + if (!width) + width = chip->width; + if (!height) + height = chip->height; + setaddrwin = chip->setaddrwin; + if (chip->regwidth) + regwidth = chip->regwidth; + if (!init_num) { + initp = chip->init_seq; + initp_num = chip->init_seq_sz; + } +} + static struct fbtft_display flex_display = { }; +static int flexfb_chip_init(const struct device *dev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(flexfb_chip_table); i++) + if (!strcmp(chip, flexfb_chip_table[i].name)) { + flexfb_chip_load_param(&flexfb_chip_table[i]); + return 0; + } + + dev_err(dev, "chip=%s is not supported\n", chip); + + return -EINVAL; +} + static int flexfb_probe_common(struct spi_device *sdev, struct platform_device *pdev) { @@ -269,102 +402,9 @@ static int flexfb_probe_common(struct spi_device *sdev, sdev ? "'SPI device'" : "'Platform device'"); if (chip) { - - if (!strcmp(chip, "st7735r")) { - if (!width) - width = 128; - if (!height) - height = 160; - if (init_num == 0) { - initp = st7735r_init; - initp_num = ARRAY_SIZE(st7735r_init); - } - - } else if (!strcmp(chip, "hx8340bn")) { - if (!width) - width = 176; - if (!height) - height = 220; - setaddrwin = 0; - if (init_num == 0) { - initp = hx8340bn_init; - initp_num = ARRAY_SIZE(hx8340bn_init); - } - - } else if (!strcmp(chip, "ili9225")) { - if (!width) - width = 176; - if (!height) - height = 220; - setaddrwin = 0; - regwidth = 16; - if (init_num == 0) { - initp = ili9225_init; - initp_num = ARRAY_SIZE(ili9225_init); - } - - } else if (!strcmp(chip, "ili9320")) { - if (!width) - width = 240; - if (!height) - height = 320; - setaddrwin = 1; - regwidth = 16; - if (init_num == 0) { - initp = ili9320_init; - initp_num = ARRAY_SIZE(ili9320_init); - } - - } else if (!strcmp(chip, "ili9325")) { - if (!width) - width = 240; - if (!height) - height = 320; - setaddrwin = 1; - regwidth = 16; - if (init_num == 0) { - initp = ili9325_init; - initp_num = ARRAY_SIZE(ili9325_init); - } - - } else if (!strcmp(chip, "ili9341")) { - if (!width) - width = 240; - if (!height) - height = 320; - setaddrwin = 0; - regwidth = 8; - if (init_num == 0) { - initp = ili9341_init; - initp_num = ARRAY_SIZE(ili9341_init); - } - - } else if (!strcmp(chip, "ssd1289")) { - if (!width) - width = 240; - if (!height) - height = 320; - setaddrwin = 2; - regwidth = 16; - if (init_num == 0) { - initp = ssd1289_init; - initp_num = ARRAY_SIZE(ssd1289_init); - } - - } else if (!strcmp(chip, "ssd1351")) { - if (!width) - width = 128; - if (!height) - height = 128; - setaddrwin = 3; - if (init_num == 0) { - initp = ssd1351_init; - initp_num = ARRAY_SIZE(ssd1351_init); - } - } else { - dev_err(dev, "chip=%s is not supported\n", chip); - return -EINVAL; - } + ret = flexfb_chip_init(dev); + if (ret) + return ret; } if (width == 0 || height == 0) { @@ -379,7 +419,7 @@ static int flexfb_probe_common(struct spi_device *sdev, fbtft_init_dbg(dev, "regwidth = %d\n", regwidth); fbtft_init_dbg(dev, "buswidth = %d\n", buswidth); - info = fbtft_framebuffer_alloc(&flex_display, dev); + info = fbtft_framebuffer_alloc(&flex_display, dev, dev->platform_data); if (!info) return -ENOMEM; diff --git a/drivers/staging/fsl-mc/README.txt b/drivers/staging/fsl-mc/README.txt new file mode 100644 index 000000000000..8214102f104b --- /dev/null +++ b/drivers/staging/fsl-mc/README.txt @@ -0,0 +1,364 @@ +Copyright (C) 2015 Freescale Semiconductor Inc. + +DPAA2 (Data Path Acceleration Architecture Gen2) +------------------------------------------------ + +This document provides an overview of the Freescale DPAA2 architecture +and how it is integrated into the Linux kernel. + +Contents summary + -DPAA2 overview + -Overview of DPAA2 objects + -DPAA2 Linux driver architecture overview + -bus driver + -dprc driver + -allocator + -dpio driver + -Ethernet + -mac + +DPAA2 Overview +-------------- + +DPAA2 is a hardware architecture designed for high-speeed network +packet processing. DPAA2 consists of sophisticated mechanisms for +processing Ethernet packets, queue management, buffer management, +autonomous L2 switching, virtual Ethernet bridging, and accelerator +(e.g. crypto) sharing. + +A DPAA2 hardware component called the Management Complex (or MC) manages the +DPAA2 hardware resources. The MC provides an object-based abstraction for +software drivers to use the DPAA2 hardware. + +The MC uses DPAA2 hardware resources such as queues, buffer pools, and +network ports to create functional objects/devices such as network +interfaces, an L2 switch, or accelerator instances. + +The MC provides memory-mapped I/O command interfaces (MC portals) +which DPAA2 software drivers use to operate on DPAA2 objects: + + +--------------------------------------+ + | OS | + | DPAA2 drivers | + | | | + +-----------------------------|--------+ + | + | (create,discover,connect + | config,use,destroy) + | + DPAA2 | + +------------------------| mc portal |-+ + | | | + | +- - - - - - - - - - - - -V- - -+ | + | | | | + | | Management Complex (MC) | | + | | | | + | +- - - - - - - - - - - - - - - -+ | + | | + | Hardware Hardware | + | Resources Objects | + | --------- ------- | + | -queues -DPRC | + | -buffer pools -DPMCP | + | -Eth MACs/ports -DPIO | + | -network interface -DPNI | + | profiles -DPMAC | + | -queue portals -DPBP | + | -MC portals ... | + | ... | + | | + +--------------------------------------+ + +The MC mediates operations such as create, discover, +connect, configuration, and destroy. Fast-path operations +on data, such as packet transmit/receive, are not mediated by +the MC and are done directly using memory mapped regions in +DPIO objects. + +Overview of DPAA2 Objects +------------------------- +The section provides a brief overview of some key objects +in the DPAA2 hardware. A simple scenario is described illustrating +the objects involved in creating a network interfaces. + +-DPRC (Datapath Resource Container) + + A DPRC is an container object that holds all the other + types of DPAA2 objects. In the example diagram below there + are 8 objects of 5 types (DPMCP, DPIO, DPBP, DPNI, and DPMAC) + in the container. + + +---------------------------------------------------------+ + | DPRC | + | | + | +-------+ +-------+ +-------+ +-------+ +-------+ | + | | DPMCP | | DPIO | | DPBP | | DPNI | | DPMAC | | + | +-------+ +-------+ +-------+ +---+---+ +---+---+ | + | | DPMCP | | DPIO | | + | +-------+ +-------+ | + | | DPMCP | | + | +-------+ | + | | + +---------------------------------------------------------+ + + From the point of view of an OS, a DPRC is bus-like. Like + a plug-and-play bus, such as PCI, DPRC commands can be used to + enumerate the contents of the DPRC, discover the hardware + objects present (including mappable regions and interrupts). + + dprc.1 (bus) + | + +--+--------+-------+-------+-------+ + | | | | | + dpmcp.1 dpio.1 dpbp.1 dpni.1 dpmac.1 + dpmcp.2 dpio.2 + dpmcp.3 + + Hardware objects can be created and destroyed dynamically, providing + the ability to hot plug/unplug objects in and out of the DPRC. + + A DPRC has a mappable mmio region (an MC portal) that can be used + to send MC commands. It has an interrupt for status events (like + hotplug). + + All objects in a container share the same hardware "isolation context". + This means that with respect to an IOMMU the isolation granularity + is at the DPRC (container) level, not at the individual object + level. + + DPRCs can be defined statically and populated with objects + via a config file passed to the MC when firmware starts + it. There is also a Linux user space tool called "restool" + that can be used to create/destroy containers and objects + dynamically. + +-DPAA2 Objects for an Ethernet Network Interface + + A typical Ethernet NIC is monolithic-- the NIC device contains TX/RX + queuing mechanisms, configuration mechanisms, buffer management, + physical ports, and interrupts. DPAA2 uses a more granular approach + utilizing multiple hardware objects. Each object has specialized + functions, and are used together by software to provide Ethernet network + interface functionality. This approach provides efficient use of finite + hardware resources, flexibility, and performance advantages. + + The diagram below shows the objects needed for a simple + network interface configuration on a system with 2 CPUs. + + +---+---+ +---+---+ + CPU0 CPU1 + +---+---+ +---+---+ + | | + +---+---+ +---+---+ + DPIO DPIO + +---+---+ +---+---+ + \ / + \ / + \ / + +---+---+ + DPNI --- DPBP,DPMCP + +---+---+ + | + | + +---+---+ + DPMAC + +---+---+ + | + port/PHY + + Below the objects are described. For each object a brief description + is provided along with a summary of the kinds of operations the object + supports and a summary of key resources of the object (mmio regions + and irqs). + + -DPMAC (Datapath Ethernet MAC): represents an Ethernet MAC, a + hardware device that connects to an Ethernet PHY and allows + physical transmission and reception of Ethernet frames. + -mmio regions: none + -irqs: dpni link change + -commands: set link up/down, link config, get stats, + irq config, enable, reset + + -DPNI (Datapath Network Interface): contains TX/RX queues, + network interface configuration, and rx buffer pool configuration + mechanisms. + -mmio regions: none + -irqs: link state + -commands: port config, offload config, queue config, + parse/classify config, irq config, enable, reset + + -DPIO (Datapath I/O): provides interfaces to enqueue and dequeue + packets and do hardware buffer pool management operations. For + optimum performance there is typically DPIO per CPU. This allows + each CPU to perform simultaneous enqueue/dequeue operations. + -mmio regions: queue operations, buffer mgmt + -irqs: data availability, congestion notification, buffer + pool depletion + -commands: irq config, enable, reset + + -DPBP (Datapath Buffer Pool): represents a hardware buffer + pool. + -mmio regions: none + -irqs: none + -commands: enable, reset + + -DPMCP (Datapath MC Portal): provides an MC command portal. + Used by drivers to send commands to the MC to manage + objects. + -mmio regions: MC command portal + -irqs: command completion + -commands: irq config, enable, reset + + Object Connections + ------------------ + Some objects have explicit relationships that must + be configured: + + -DPNI <--> DPMAC + -DPNI <--> DPNI + -DPNI <--> L2-switch-port + A DPNI must be connected to something such as a DPMAC, + another DPNI, or L2 switch port. The DPNI connection + is made via a DPRC command. + + +-------+ +-------+ + | DPNI | | DPMAC | + +---+---+ +---+---+ + | | + +==========+ + + -DPNI <--> DPBP + A network interface requires a 'buffer pool' (DPBP + object) which provides a list of pointers to memory + where received Ethernet data is to be copied. The + Ethernet driver configures the DPBPs associated with + the network interface. + + Interrupts + ---------- + All interrupts generated by DPAA2 objects are message + interrupts. At the hardware level message interrupts + generated by devices will normally have 3 components-- + 1) a non-spoofable 'device-id' expressed on the hardware + bus, 2) an address, 3) a data value. + + In the case of DPAA2 devices/objects, all objects in the + same container/DPRC share the same 'device-id'. + For ARM-based SoC this is the same as the stream ID. + + +DPAA2 Linux Driver Overview +--------------------------- + +This section provides an overview of the Linux kernel drivers for +DPAA2-- 1) the bus driver and associated "DPAA2 infrastructure" +drivers and 2) functional object drivers (such as Ethernet). + +As described previously, a DPRC is a container that holds the other +types of DPAA2 objects. It is functionally similar to a plug-and-play +bus controller. + +Each object in the DPRC is a Linux "device" and is bound to a driver. +The diagram below shows the Linux drivers involved in a networking +scenario and the objects bound to each driver. A brief description +of each driver follows. + + +------------+ + | OS Network | + | Stack | + +------------+ +------------+ + | Allocator |. . . . . . . | Ethernet | + |(dpmcp,dpbp)| | (dpni) | + +-.----------+ +---+---+----+ + . . ^ | + . . <data avail, | |<enqueue, + . . tx confirm> | | dequeue> + +-------------+ . | | + | DPRC driver | . +---+---V----+ +---------+ + | (dprc) | . . . . . .| DPIO driver| | MAC | + +----------+--+ | (dpio) | | (dpmac) | + | +------+-----+ +-----+---+ + |<dev add/remove> | | + | | | + +----+--------------+ | +--+---+ + | mc-bus driver | | | PHY | + | | | |driver| + | /fsl-mc@80c000000 | | +--+---+ + +-------------------+ | | + | | + ================================ HARDWARE =========|=================|====== + DPIO | + | | + DPNI---DPBP | + | | + DPMAC | + | | + PHY ---------------+ + ===================================================|======================== + +A brief description of each driver is provided below. + + mc-bus driver + ------------- + The mc-bus driver is a platform driver and is probed from an + "/fsl-mc@xxxx" node in the device tree passed in by boot firmware. + It is responsible for bootstrapping the DPAA2 kernel infrastructure. + Key functions include: + -registering a new bus type named "fsl-mc" with the kernel, + and implementing bus call-backs (e.g. match/uevent/dev_groups) + -implemeting APIs for DPAA2 driver registration and for device + add/remove + -creates an MSI irq domain + -do a device add of the 'root' DPRC device, which is needed + to bootstrap things + + DPRC driver + ----------- + The dprc-driver is bound DPRC objects and does runtime management + of a bus instance. It performs the initial bus scan of the DPRC + and handles interrupts for container events such as hot plug. + + Allocator + ---------- + Certain objects such as DPMCP and DPBP are generic and fungible, + and are intended to be used by other drivers. For example, + the DPAA2 Ethernet driver needs: + -DPMCPs to send MC commands, to configure network interfaces + -DPBPs for network buffer pools + + The allocator driver registers for these allocatable object types + and those objects are bound to the allocator when the bus is probed. + The allocator maintains a pool of objects that are available for + allocation by other DPAA2 drivers. + + DPIO driver + ----------- + The DPIO driver is bound to DPIO objects and provides services that allow + other drivers such as the Ethernet driver to receive and transmit data. + Key services include: + -data availability notifications + -hardware queuing operations (enqueue and dequeue of data) + -hardware buffer pool management + + There is typically one DPIO object per physical CPU for optimum + performance, allowing each CPU to simultaneously enqueue + and dequeue data. + + The DPIO driver operates on behalf of all DPAA2 drivers + active in the kernel-- Ethernet, crypto, compression, + etc. + + Ethernet + -------- + The Ethernet driver is bound to a DPNI and implements the kernel + interfaces needed to connect the DPAA2 network interface to + the network stack. + + Each DPNI corresponds to a Linux network interface. + + MAC driver + ---------- + An Ethernet PHY is an off-chip, board specific component and is managed + by the appropriate PHY driver via an mdio bus. The MAC driver + plays a role of being a proxy between the PHY driver and the + MC. It does this proxy via the MC commands to a DPMAC object. diff --git a/drivers/staging/fsl-mc/TODO b/drivers/staging/fsl-mc/TODO index d78288b4e721..389436891b93 100644 --- a/drivers/staging/fsl-mc/TODO +++ b/drivers/staging/fsl-mc/TODO @@ -1,13 +1,31 @@ -* Add README file (with ASCII art) describing relationships between - DPAA2 objects and how combine them to make a NIC, an LS2 switch, etc. - Also, define all acronyms used. - * Decide if multiple root fsl-mc buses will be supported per Linux instance, and if so add support for this. * Add at least one device driver for a DPAA2 object (child device of the - fsl-mc bus). + fsl-mc bus). Most likely candidate for this is adding DPAA2 Ethernet + driver support, which depends on drivers for several objects: DPNI, + DPIO, DPMAC. Other pre-requisites include: + + * interrupt support. for meaningful driver support we need + interrupts, and thus need message interrupt support by the bus + driver. + -Note: this has dependencies on generic MSI support work + in process upstream, see [1] and [2]. + + * Management Complex (MC) command serialization. locking mechanisms + are needed by drivers to serialize commands sent to the MC, including + from atomic context. + + * MC firmware uprev. The MC firmware upon which the fsl-mc + bus driver and DPAA2 object drivers are based is continuing + to evolve, so minor updates are needed to keep in sync with binary + interface changes to the MC. + +* Cleanup Please send any patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org>, german.rivera@freescale.com, devel@driverdev.osuosl.org, linux-kernel@vger.kernel.org + +[1] https://lkml.org/lkml/2015/7/9/93 +[2] https://lkml.org/lkml/2015/7/7/712 diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index 5dd9cdfae30c..d585041041c7 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -134,7 +134,7 @@ void cfs_get_random_bytes(void *buf, int size); /* container_of depends on "likely" which is defined in libcfs_private.h */ static inline void *__container_of(void *ptr, unsigned long shift) { - if (unlikely(IS_ERR(ptr) || ptr == NULL)) + if (IS_ERR_OR_NULL(ptr)) return ptr; return (char *)ptr - shift; } diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_string.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_string.h index 509dc1e5c3b1..478e9582ff54 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_string.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_string.h @@ -102,6 +102,4 @@ int cfs_ip_addr_parse(char *str, int len, struct list_head *list); int cfs_ip_addr_match(__u32 addr, struct list_head *list); void cfs_ip_addr_free(struct list_head *list); -#define strtoul(str, endp, base) simple_strtoul(str, endp, base) - #endif diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c index f429d25306c1..24b2c978dfb6 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c @@ -1390,7 +1390,7 @@ static int kiblnd_create_fmr_pool(kib_fmr_poolset_t *fps, .max_pages_per_fmr = LNET_MAX_PAYLOAD/PAGE_SIZE, .page_shift = PAGE_SHIFT, .access = (IB_ACCESS_LOCAL_WRITE | - IB_ACCESS_REMOTE_WRITE), + IB_ACCESS_REMOTE_WRITE), .pool_size = fps->fps_pool_size, .dirty_watermark = fps->fps_flush_trigger, .flush_function = NULL, diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h index f5d1d9f8f1ed..2991be85d8b3 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h @@ -48,7 +48,7 @@ #include <linux/uio.h> #include <linux/uaccess.h> -#include <asm/io.h> +#include <linux/io.h> #include <linux/fs.h> #include <linux/file.h> @@ -120,7 +120,7 @@ extern kib_tunables_t kiblnd_tunables; #define IBLND_CREDIT_HIGHWATER_V1 7 /* V1 only : when eagerly to return credits */ #define IBLND_CREDITS_DEFAULT 8 /* default # of peer credits */ -#define IBLND_CREDITS_MAX ((typeof(((kib_msg_t*) 0)->ibm_credits)) - 1) /* Max # of peer credits */ +#define IBLND_CREDITS_MAX ((typeof(((kib_msg_t *) 0)->ibm_credits)) - 1) /* Max # of peer credits */ #define IBLND_MSG_QUEUE_SIZE(v) ((v) == IBLND_MSG_VERSION_1 ? \ IBLND_MSG_QUEUE_SIZE_V1 : \ @@ -519,7 +519,7 @@ typedef struct kib_rx /* receive message */ enum ib_wc_status rx_status; /* completion status */ kib_msg_t *rx_msg; /* message buffer (host vaddr) */ __u64 rx_msgaddr; /* message buffer (I/O addr) */ - DECLARE_PCI_UNMAP_ADDR (rx_msgunmap); /* for dma_unmap_single() */ + DECLARE_PCI_UNMAP_ADDR(rx_msgunmap); /* for dma_unmap_single() */ struct ib_recv_wr rx_wrq; /* receive work item... */ struct ib_sge rx_sge; /* ...and its memory */ } kib_rx_t; @@ -546,7 +546,7 @@ typedef struct kib_tx /* transmit message */ * completion */ kib_msg_t *tx_msg; /* message buffer (host vaddr) */ __u64 tx_msgaddr; /* message buffer (I/O addr) */ - DECLARE_PCI_UNMAP_ADDR (tx_msgunmap); /* for dma_unmap_single() */ + DECLARE_PCI_UNMAP_ADDR(tx_msgunmap); /* for dma_unmap_single() */ int tx_nwrq; /* # send work items */ struct ib_send_wr *tx_wrq; /* send work items... */ struct ib_sge *tx_sge; /* ...and their memory */ @@ -647,14 +647,14 @@ extern void kiblnd_hdev_destroy(kib_hca_dev_t *hdev); static inline void kiblnd_hdev_addref_locked(kib_hca_dev_t *hdev) { - LASSERT (atomic_read(&hdev->ibh_ref) > 0); + LASSERT(atomic_read(&hdev->ibh_ref) > 0); atomic_inc(&hdev->ibh_ref); } static inline void kiblnd_hdev_decref(kib_hca_dev_t *hdev) { - LASSERT (atomic_read(&hdev->ibh_ref) > 0); + LASSERT(atomic_read(&hdev->ibh_ref) > 0); if (atomic_dec_and_test(&hdev->ibh_ref)) kiblnd_hdev_destroy(hdev); } @@ -701,7 +701,7 @@ do { \ do { \ CDEBUG(D_NET, "peer[%p] -> %s (%d)++\n", \ (peer), libcfs_nid2str((peer)->ibp_nid), \ - atomic_read (&(peer)->ibp_refcount)); \ + atomic_read(&(peer)->ibp_refcount)); \ atomic_inc(&(peer)->ibp_refcount); \ } while (0) @@ -709,32 +709,32 @@ do { \ do { \ CDEBUG(D_NET, "peer[%p] -> %s (%d)--\n", \ (peer), libcfs_nid2str((peer)->ibp_nid), \ - atomic_read (&(peer)->ibp_refcount)); \ + atomic_read(&(peer)->ibp_refcount)); \ LASSERT_ATOMIC_POS(&(peer)->ibp_refcount); \ if (atomic_dec_and_test(&(peer)->ibp_refcount)) \ kiblnd_destroy_peer(peer); \ } while (0) static inline struct list_head * -kiblnd_nid2peerlist (lnet_nid_t nid) +kiblnd_nid2peerlist(lnet_nid_t nid) { unsigned int hash = ((unsigned int)nid) % kiblnd_data.kib_peer_hash_size; - return (&kiblnd_data.kib_peers [hash]); + return &kiblnd_data.kib_peers[hash]; } static inline int -kiblnd_peer_active (kib_peer_t *peer) +kiblnd_peer_active(kib_peer_t *peer) { /* Am I in the peer hash table? */ - return (!list_empty(&peer->ibp_list)); + return !list_empty(&peer->ibp_list); } static inline kib_conn_t * -kiblnd_get_conn_locked (kib_peer_t *peer) +kiblnd_get_conn_locked(kib_peer_t *peer) { - LASSERT (!list_empty(&peer->ibp_conns)); + LASSERT(!list_empty(&peer->ibp_conns)); /* just return the first connection */ return list_entry(peer->ibp_conns.next, kib_conn_t, ibc_list); @@ -751,7 +751,7 @@ kiblnd_send_keepalive(kib_conn_t *conn) static inline int kiblnd_need_noop(kib_conn_t *conn) { - LASSERT (conn->ibc_state >= IBLND_CONN_ESTABLISHED); + LASSERT(conn->ibc_state >= IBLND_CONN_ESTABLISHED); if (conn->ibc_outstanding_credits < IBLND_CREDITS_HIGHWATER(conn->ibc_version) && @@ -788,7 +788,7 @@ kiblnd_abort_receives(kib_conn_t *conn) } static inline const char * -kiblnd_queue2str (kib_conn_t *conn, struct list_head *q) +kiblnd_queue2str(kib_conn_t *conn, struct list_head *q) { if (q == &conn->ibc_tx_queue) return "tx_queue"; @@ -815,43 +815,43 @@ kiblnd_queue2str (kib_conn_t *conn, struct list_head *q) #define IBLND_WID_MASK 3UL static inline __u64 -kiblnd_ptr2wreqid (void *ptr, int type) +kiblnd_ptr2wreqid(void *ptr, int type) { unsigned long lptr = (unsigned long)ptr; - LASSERT ((lptr & IBLND_WID_MASK) == 0); - LASSERT ((type & ~IBLND_WID_MASK) == 0); + LASSERT((lptr & IBLND_WID_MASK) == 0); + LASSERT((type & ~IBLND_WID_MASK) == 0); return (__u64)(lptr | type); } static inline void * -kiblnd_wreqid2ptr (__u64 wreqid) +kiblnd_wreqid2ptr(__u64 wreqid) { return (void *)(((unsigned long)wreqid) & ~IBLND_WID_MASK); } static inline int -kiblnd_wreqid2type (__u64 wreqid) +kiblnd_wreqid2type(__u64 wreqid) { - return (wreqid & IBLND_WID_MASK); + return wreqid & IBLND_WID_MASK; } static inline void -kiblnd_set_conn_state (kib_conn_t *conn, int state) +kiblnd_set_conn_state(kib_conn_t *conn, int state) { conn->ibc_state = state; mb(); } static inline void -kiblnd_init_msg (kib_msg_t *msg, int type, int body_nob) +kiblnd_init_msg(kib_msg_t *msg, int type, int body_nob) { msg->ibm_type = type; msg->ibm_nob = offsetof(kib_msg_t, ibm_u) + body_nob; } static inline int -kiblnd_rd_size (kib_rdma_desc_t *rd) +kiblnd_rd_size(kib_rdma_desc_t *rd) { int i; int size; @@ -887,7 +887,7 @@ kiblnd_rd_consume_frag(kib_rdma_desc_t *rd, int index, __u32 nob) rd->rd_frags[index].rf_addr += nob; rd->rd_frags[index].rf_nob -= nob; } else { - index ++; + index++; } return index; @@ -896,8 +896,8 @@ kiblnd_rd_consume_frag(kib_rdma_desc_t *rd, int index, __u32 nob) static inline int kiblnd_rd_msg_size(kib_rdma_desc_t *rd, int msgtype, int n) { - LASSERT (msgtype == IBLND_MSG_GET_REQ || - msgtype == IBLND_MSG_PUT_ACK); + LASSERT(msgtype == IBLND_MSG_GET_REQ || + msgtype == IBLND_MSG_PUT_ACK); return msgtype == IBLND_MSG_GET_REQ ? offsetof(kib_get_msg_t, ibgm_rd.rd_frags[n]) : @@ -982,53 +982,53 @@ int kiblnd_pmr_pool_map(kib_pmr_poolset_t *pps, kib_hca_dev_t *hdev, kib_rdma_desc_t *rd, __u64 *iova, kib_phys_mr_t **pp_pmr); void kiblnd_pmr_pool_unmap(kib_phys_mr_t *pmr); -int kiblnd_startup (lnet_ni_t *ni); -void kiblnd_shutdown (lnet_ni_t *ni); -int kiblnd_ctl (lnet_ni_t *ni, unsigned int cmd, void *arg); -void kiblnd_query (struct lnet_ni *ni, lnet_nid_t nid, unsigned long *when); +int kiblnd_startup(lnet_ni_t *ni); +void kiblnd_shutdown(lnet_ni_t *ni); +int kiblnd_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg); +void kiblnd_query(struct lnet_ni *ni, lnet_nid_t nid, unsigned long *when); int kiblnd_tunables_init(void); void kiblnd_tunables_fini(void); -int kiblnd_connd (void *arg); +int kiblnd_connd(void *arg); int kiblnd_scheduler(void *arg); int kiblnd_thread_start(int (*fn)(void *arg), void *arg, char *name); -int kiblnd_failover_thread (void *arg); +int kiblnd_failover_thread(void *arg); int kiblnd_alloc_pages(kib_pages_t **pp, int cpt, int npages); -void kiblnd_free_pages (kib_pages_t *p); +void kiblnd_free_pages(kib_pages_t *p); int kiblnd_cm_callback(struct rdma_cm_id *cmid, struct rdma_cm_event *event); int kiblnd_translate_mtu(int value); int kiblnd_dev_failover(kib_dev_t *dev); -int kiblnd_create_peer (lnet_ni_t *ni, kib_peer_t **peerp, lnet_nid_t nid); -void kiblnd_destroy_peer (kib_peer_t *peer); -void kiblnd_destroy_dev (kib_dev_t *dev); -void kiblnd_unlink_peer_locked (kib_peer_t *peer); -void kiblnd_peer_alive (kib_peer_t *peer); -kib_peer_t *kiblnd_find_peer_locked (lnet_nid_t nid); -void kiblnd_peer_connect_failed (kib_peer_t *peer, int active, int error); -int kiblnd_close_stale_conns_locked (kib_peer_t *peer, +int kiblnd_create_peer(lnet_ni_t *ni, kib_peer_t **peerp, lnet_nid_t nid); +void kiblnd_destroy_peer(kib_peer_t *peer); +void kiblnd_destroy_dev(kib_dev_t *dev); +void kiblnd_unlink_peer_locked(kib_peer_t *peer); +void kiblnd_peer_alive(kib_peer_t *peer); +kib_peer_t *kiblnd_find_peer_locked(lnet_nid_t nid); +void kiblnd_peer_connect_failed(kib_peer_t *peer, int active, int error); +int kiblnd_close_stale_conns_locked(kib_peer_t *peer, int version, __u64 incarnation); -int kiblnd_close_peer_conns_locked (kib_peer_t *peer, int why); +int kiblnd_close_peer_conns_locked(kib_peer_t *peer, int why); void kiblnd_connreq_done(kib_conn_t *conn, int status); -kib_conn_t *kiblnd_create_conn (kib_peer_t *peer, struct rdma_cm_id *cmid, +kib_conn_t *kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid, int state, int version); -void kiblnd_destroy_conn (kib_conn_t *conn); -void kiblnd_close_conn (kib_conn_t *conn, int error); -void kiblnd_close_conn_locked (kib_conn_t *conn, int error); +void kiblnd_destroy_conn(kib_conn_t *conn); +void kiblnd_close_conn(kib_conn_t *conn, int error); +void kiblnd_close_conn_locked(kib_conn_t *conn, int error); -int kiblnd_init_rdma (kib_conn_t *conn, kib_tx_t *tx, int type, +int kiblnd_init_rdma(kib_conn_t *conn, kib_tx_t *tx, int type, int nob, kib_rdma_desc_t *dstrd, __u64 dstcookie); -void kiblnd_launch_tx (lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid); -void kiblnd_queue_tx_locked (kib_tx_t *tx, kib_conn_t *conn); -void kiblnd_queue_tx (kib_tx_t *tx, kib_conn_t *conn); -void kiblnd_init_tx_msg (lnet_ni_t *ni, kib_tx_t *tx, int type, int body_nob); -void kiblnd_txlist_done (lnet_ni_t *ni, struct list_head *txlist, +void kiblnd_launch_tx(lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid); +void kiblnd_queue_tx_locked(kib_tx_t *tx, kib_conn_t *conn); +void kiblnd_queue_tx(kib_tx_t *tx, kib_conn_t *conn); +void kiblnd_init_tx_msg(lnet_ni_t *ni, kib_tx_t *tx, int type, int body_nob); +void kiblnd_txlist_done(lnet_ni_t *ni, struct list_head *txlist, int status); void kiblnd_check_sends (kib_conn_t *conn); @@ -1036,10 +1036,10 @@ void kiblnd_qp_event(struct ib_event *event, void *arg); void kiblnd_cq_event(struct ib_event *event, void *arg); void kiblnd_cq_completion(struct ib_cq *cq, void *arg); -void kiblnd_pack_msg (lnet_ni_t *ni, kib_msg_t *msg, int version, +void kiblnd_pack_msg(lnet_ni_t *ni, kib_msg_t *msg, int version, int credits, lnet_nid_t dstnid, __u64 dststamp); int kiblnd_unpack_msg(kib_msg_t *msg, int nob); -int kiblnd_post_rx (kib_rx_t *rx, int credit); +int kiblnd_post_rx(kib_rx_t *rx, int credit); int kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg); int kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 477aa8b76f32..5a8ebe1b3c84 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -3133,8 +3133,7 @@ kiblnd_connd(void *arg) dropped_lock = 0; if (!list_empty(&kiblnd_data.kib_connd_zombies)) { - conn = list_entry(kiblnd_data. \ - kib_connd_zombies.next, + conn = list_entry(kiblnd_data.kib_connd_zombies.next, kib_conn_t, ibc_list); list_del(&conn->ibc_list); diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index 7c5185a2a795..257de3537671 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -203,7 +203,8 @@ sfw_deactivate_session(void) sfw_batch_t *tsb; sfw_test_case_t *tsc; - if (sn == NULL) return; + if (sn == NULL) + return; LASSERT(!sn->sn_timer_active); @@ -613,7 +614,8 @@ sfw_destroy_test_instance(sfw_test_instance_t *tsi) srpc_client_rpc_t *rpc; sfw_test_unit_t *tsu; - if (!tsi->tsi_is_client) goto clean; + if (!tsi->tsi_is_client) + goto clean; tsi->tsi_ops->tso_fini(tsi); @@ -1700,7 +1702,8 @@ sfw_startup(void) for (i = 0; ; i++) { sv = &sfw_services[i]; - if (sv->sv_name == NULL) break; + if (sv->sv_name == NULL) + break; sv->sv_bulk_ready = NULL; sv->sv_handler = sfw_handle_server_rpc; @@ -1717,7 +1720,8 @@ sfw_startup(void) } /* about to sfw_shutdown, no need to add buffer */ - if (error) continue; + if (error) + continue; rc = srpc_service_add_buffers(sv, sv->sv_wi_total); if (rc != 0) { diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h index 513c81f43d6e..6b14406b2920 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h @@ -64,98 +64,6 @@ #define LTIME_S(time) (time.tv_sec) -/* inode_dio_wait(i) use as-is for write lock */ -# define inode_dio_write_done(i) do {} while (0) /* for write unlock */ -# define inode_dio_read(i) atomic_inc(&(i)->i_dio_count) -/* inode_dio_done(i) use as-is for read unlock */ - - -#ifndef FS_HAS_FIEMAP -#define FS_HAS_FIEMAP (0) -#endif - -#define ll_vfs_rmdir(dir, entry, mnt) vfs_rmdir(dir, entry) -#define ll_vfs_mkdir(inode, dir, mnt, mode) vfs_mkdir(inode, dir, mode) -#define ll_vfs_link(old, mnt, dir, new, mnt1) vfs_link(old, dir, new) -#define ll_vfs_unlink(inode, entry, mnt) vfs_unlink(inode, entry) -#define ll_vfs_mknod(dir, entry, mnt, mode, dev) \ - vfs_mknod(dir, entry, mode, dev) -#define ll_security_inode_unlink(dir, entry, mnt) \ - security_inode_unlink(dir, entry) -#define ll_vfs_rename(old, old_dir, mnt, new, new_dir, mnt1) \ - vfs_rename(old, old_dir, new, new_dir, NULL, 0) - -#define cfs_bio_io_error(a, b) bio_io_error((a)) -#define cfs_bio_endio(a, b, c) bio_endio((a), (c)) - -#define cfs_path_put(nd) path_put(&(nd)->path) - - -#ifndef SLAB_DESTROY_BY_RCU -#define SLAB_DESTROY_BY_RCU 0 -#endif - - - -static inline int -ll_quota_on(struct super_block *sb, int off, int ver, char *name, int remount) -{ - int rc; - - if (sb->s_qcop->quota_on) { - struct path path; - - rc = kern_path(name, LOOKUP_FOLLOW, &path); - if (!rc) - return rc; - rc = sb->s_qcop->quota_on(sb, off, ver - , &path - ); - path_put(&path); - return rc; - } else - return -ENOSYS; -} - -static inline int ll_quota_off(struct super_block *sb, int off, int remount) -{ - if (sb->s_qcop->quota_off) { - return sb->s_qcop->quota_off(sb, off - ); - } else - return -ENOSYS; -} - - -# define ll_vfs_dq_init dquot_initialize -# define ll_vfs_dq_drop dquot_drop -# define ll_vfs_dq_transfer dquot_transfer -# define ll_vfs_dq_off(sb, remount) dquot_suspend(sb, -1) - - - - - -#define queue_max_phys_segments(rq) queue_max_segments(rq) -#define queue_max_hw_segments(rq) queue_max_segments(rq) - - -#define ll_d_hlist_node hlist_node -#define ll_d_hlist_empty(list) hlist_empty(list) -#define ll_d_hlist_entry(ptr, type, name) hlist_entry(ptr.first, type, name) -#define ll_d_hlist_for_each(tmp, i_dentry) hlist_for_each(tmp, i_dentry) -#define ll_d_hlist_for_each_entry(dentry, p, i_dentry, alias) \ - p = NULL; hlist_for_each_entry(dentry, i_dentry, alias) - - -#define bio_hw_segments(q, bio) 0 - - -#define ll_pagevec_init(pv, cold) do {} while (0) -#define ll_pagevec_add(pv, pg) (0) -#define ll_pagevec_lru_add_file(pv) do {} while (0) - - #ifndef QUOTA_OK # define QUOTA_OK 0 #endif @@ -163,17 +71,6 @@ static inline int ll_quota_off(struct super_block *sb, int off, int remount) # define NO_QUOTA (-EDQUOT) #endif -#ifndef SEEK_DATA -#define SEEK_DATA 3 /* seek to the next data */ -#endif -#ifndef SEEK_HOLE -#define SEEK_HOLE 4 /* seek to the next hole */ -#endif - -#ifndef FMODE_UNSIGNED_OFFSET -#define FMODE_UNSIGNED_OFFSET ((__force fmode_t)0x2000) -#endif - #if !defined(_ASM_GENERIC_BITOPS_EXT2_NON_ATOMIC_H_) && !defined(ext2_set_bit) # define ext2_set_bit __test_and_set_bit_le # define ext2_clear_bit __test_and_clear_bit_le @@ -182,20 +79,4 @@ static inline int ll_quota_off(struct super_block *sb, int off, int remount) # define ext2_find_next_zero_bit find_next_zero_bit_le #endif -#ifdef ATTR_TIMES_SET -# define TIMES_SET_FLAGS (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET) -#else -# define TIMES_SET_FLAGS (ATTR_MTIME_SET | ATTR_ATIME_SET) -#endif - - -#include <linux/version.h> -#include <linux/fs.h> - -# define ll_umode_t umode_t - -#include <linux/dcache.h> - -# define ll_dirty_inode(inode, flag) (inode)->i_sb->s_op->dirty_inode((inode), flag) - #endif /* _COMPAT25_H */ diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h b/drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h index 14562788e4e0..ebe8d68ed813 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h @@ -60,18 +60,6 @@ truncate_complete_page(struct address_space *mapping, struct page *page) ll_delete_from_page_cache(page); } -#ifdef ATTR_OPEN -# define ATTR_FROM_OPEN ATTR_OPEN -#else -# ifndef ATTR_FROM_OPEN -# define ATTR_FROM_OPEN 0 -# endif -#endif /* ATTR_OPEN */ - -#ifndef ATTR_RAW -#define ATTR_RAW 0 -#endif - #ifndef ATTR_CTIME_SET /* * set ATTR_CTIME_SET to a high value to avoid any risk of collision with other diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h index 77a7de98fc8e..3bb2f8b0c309 100644 --- a/drivers/staging/lustre/lustre/include/lustre_net.h +++ b/drivers/staging/lustre/lustre/include/lustre_net.h @@ -2183,7 +2183,7 @@ struct ptlrpcd_ctl { */ struct ptlrpc_request_set *pc_set; /** - * Thread name used in cfs_daemonize() + * Thread name used in kthread_run() */ char pc_name[16]; /** diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 55452e562bd4..9ad8c268da10 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -1472,7 +1472,7 @@ static inline bool filename_is_volatile(const char *name, int namelen, int *idx) } /* we have an idx, read it */ start = name + LUSTRE_VOLATILE_HDR_LEN + 1; - *idx = strtoul(start, &end, 0); + *idx = simple_strtoul(start, &end, 0); /* error cases: * no digit, no trailing :, negative value */ diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c index 764f98684d74..badd227e4f67 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c @@ -656,7 +656,8 @@ int target_pack_pool_reply(struct ptlrpc_request *req) } EXPORT_SYMBOL(target_pack_pool_reply); -int target_send_reply_msg(struct ptlrpc_request *req, int rc, int fail_id) +static int +target_send_reply_msg(struct ptlrpc_request *req, int rc, int fail_id) { if (OBD_FAIL_CHECK_ORSET(fail_id & ~OBD_FAIL_ONCE, OBD_FAIL_ONCE)) { DEBUG_REQ(D_ERROR, req, "dropping reply"); diff --git a/drivers/staging/lustre/lustre/libcfs/libcfs_string.c b/drivers/staging/lustre/lustre/libcfs/libcfs_string.c index 76d4392bd282..efe5e667a2e5 100644 --- a/drivers/staging/lustre/lustre/libcfs/libcfs_string.c +++ b/drivers/staging/lustre/lustre/libcfs/libcfs_string.c @@ -231,7 +231,7 @@ cfs_str2num_check(char *str, int nob, unsigned *num, char *endp; str = cfs_trimwhite(str); - *num = strtoul(str, &endp, 0); + *num = simple_strtoul(str, &endp, 0); if (endp == str) return 0; @@ -400,7 +400,7 @@ cfs_expr_list_free(struct cfs_expr_list *expr_list) struct cfs_range_expr *expr; expr = list_entry(expr_list->el_exprs.next, - struct cfs_range_expr, re_link), + struct cfs_range_expr, re_link); list_del(&expr->re_link); LIBCFS_FREE(expr, sizeof(*expr)); } diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c index aa3fffed1519..fbbc8a7e308d 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c @@ -114,7 +114,7 @@ int cfs_crypto_hash_digest(unsigned char alg_id, crypto_free_hash(hdesc.tfm); return -ENOSPC; } - sg_init_one(&sl, (void *)buf, buf_len); + sg_init_one(&sl, buf, buf_len); hdesc.flags = 0; err = crypto_hash_digest(&hdesc, &sl, sl.length, hash); @@ -165,7 +165,7 @@ int cfs_crypto_hash_update(struct cfs_crypto_hash_desc *hdesc, { struct scatterlist sl; - sg_init_one(&sl, (void *)buf, buf_len); + sg_init_one(&sl, buf, buf_len); return crypto_hash_update((struct hash_desc *)hdesc, &sl, sl.length); } diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c index e962f89683a6..78acff068217 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c @@ -49,7 +49,7 @@ int libcfs_ioctl_getdata(char *buf, char *end, void *arg) hdr = (struct libcfs_ioctl_hdr *)buf; data = (struct libcfs_ioctl_data *)buf; - if (copy_from_user(buf, (void *)arg, sizeof(*hdr))) + if (copy_from_user(buf, arg, sizeof(*hdr))) return -EFAULT; if (hdr->ioc_version != LIBCFS_IOCTL_VERSION) { @@ -69,7 +69,7 @@ int libcfs_ioctl_getdata(char *buf, char *end, void *arg) } orig_len = hdr->ioc_len; - if (copy_from_user(buf, (void *)arg, hdr->ioc_len)) + if (copy_from_user(buf, arg, hdr->ioc_len)) return -EFAULT; if (orig_len != data->ioc_len) return -EINVAL; diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c index 7b008a64707d..b86685912d28 100644 --- a/drivers/staging/lustre/lustre/llite/dcache.c +++ b/drivers/staging/lustre/lustre/llite/dcache.c @@ -250,7 +250,6 @@ void ll_intent_release(struct lookup_intent *it) void ll_invalidate_aliases(struct inode *inode) { struct dentry *dentry; - struct ll_d_hlist_node *p; LASSERT(inode != NULL); @@ -258,7 +257,7 @@ void ll_invalidate_aliases(struct inode *inode) inode->i_ino, inode->i_generation, inode); ll_lock_dcache(inode); - ll_d_hlist_for_each_entry(dentry, p, &inode->i_dentry, d_u.d_alias) { + hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) { CDEBUG(D_DENTRY, "dentry in drop %pd (%p) parent %p inode %p flags %d\n", dentry, dentry, dentry->d_parent, d_inode(dentry), dentry->d_flags); diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 3d746a94f92e..769b61193d87 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -203,7 +203,6 @@ static int ll_dir_filler(void *_hash, struct page *page0) CDEBUG(D_VFSTRACE, "read %d/%d pages\n", nrdpgs, npages); - ll_pagevec_init(&lru_pvec, 0); for (i = 1; i < npages; i++) { unsigned long offset; int ret; @@ -228,15 +227,12 @@ static int ll_dir_filler(void *_hash, struct page *page0) GFP_KERNEL); if (ret == 0) { unlock_page(page); - if (ll_pagevec_add(&lru_pvec, page) == 0) - ll_pagevec_lru_add_file(&lru_pvec); } else { CDEBUG(D_VFSTRACE, "page %lu add to page cache failed: %d\n", offset, ret); } page_cache_release(page); } - ll_pagevec_lru_add_file(&lru_pvec); if (page_pool != &page0) kfree(page_pool); diff --git a/drivers/staging/lustre/lustre/llite/llite_capa.c b/drivers/staging/lustre/lustre/llite/llite_capa.c index a6268718b76e..24590ae36090 100644 --- a/drivers/staging/lustre/lustre/llite/llite_capa.c +++ b/drivers/staging/lustre/lustre/llite/llite_capa.c @@ -70,7 +70,8 @@ static unsigned long long ll_capa_renewal_retries; static int ll_update_capa(struct obd_capa *ocapa, struct lustre_capa *capa); -static inline void update_capa_timer(struct obd_capa *ocapa, unsigned long expiry) +static inline void update_capa_timer(struct obd_capa *ocapa, + unsigned long expiry) { if (time_before(expiry, ll_capa_timer.expires) || !timer_pending(&ll_capa_timer)) { @@ -102,13 +103,13 @@ static inline int have_expired_capa(void) spin_lock(&capa_lock); if (!list_empty(ll_capa_list)) { ocapa = list_entry(ll_capa_list->next, struct obd_capa, - c_list); + c_list); expired = capa_is_to_expire(ocapa); if (!expired) update_capa_timer(ocapa, capa_renewal_time(ocapa)); } else if (!list_empty(&ll_idle_capas)) { ocapa = list_entry(ll_idle_capas.next, struct obd_capa, - c_list); + c_list); expired = capa_is_expired(ocapa); if (!expired) update_capa_timer(ocapa, ocapa->c_expiry); @@ -165,7 +166,8 @@ static void ll_delete_capa(struct obd_capa *ocapa) /* three places where client capa is deleted: * 1. capa_thread_main(), main place to delete expired capa. * 2. ll_clear_inode_capas() in ll_clear_inode(). - * 3. ll_truncate_free_capa() delete truncate capa explicitly in ll_setattr_ost(). + * 3. ll_truncate_free_capa() delete truncate capa explicitly in + * ll_setattr_ost(). */ static int capa_thread_main(void *unused) { @@ -206,7 +208,8 @@ static int capa_thread_main(void *unused) * lock. */ /* ibits may be changed by ll_have_md_lock() so we have - * to set it each time */ + * to set it each time + */ ibits = MDS_INODELOCK_LOOKUP; if (capa_for_mds(&ocapa->c_capa) && !S_ISDIR(ocapa->u.cli.inode->i_mode) && @@ -225,14 +228,15 @@ static int capa_thread_main(void *unused) if (capa_for_oss(&ocapa->c_capa) && obd_capa_open_count(ocapa) == 0) { /* oss capa with open count == 0 won't renew, - * move to idle list */ + * move to idle list + */ sort_add_capa(ocapa, &ll_idle_capas); continue; } /* NB iput() is in ll_update_capa() */ inode = igrab(ocapa->u.cli.inode); - if (inode == NULL) { + if (!inode) { DEBUG_CAPA(D_ERROR, &ocapa->c_capa, "igrab failed for"); continue; @@ -255,7 +259,7 @@ static int capa_thread_main(void *unused) update_capa_timer(next, capa_renewal_time(next)); list_for_each_entry_safe(ocapa, tmp, &ll_idle_capas, - c_list) { + c_list) { if (!capa_is_expired(ocapa)) { if (!next) update_capa_timer(ocapa, @@ -299,11 +303,11 @@ int ll_capa_thread_start(void) task = kthread_run(capa_thread_main, NULL, "ll_capa"); if (IS_ERR(task)) { CERROR("cannot start expired capa thread: rc %ld\n", - PTR_ERR(task)); + PTR_ERR(task)); return PTR_ERR(task); } wait_event(ll_capa_thread.t_ctl_waitq, - thread_is_running(&ll_capa_thread)); + thread_is_running(&ll_capa_thread)); return 0; } @@ -313,7 +317,7 @@ void ll_capa_thread_stop(void) thread_set_flags(&ll_capa_thread, SVC_STOPPING); wake_up(&ll_capa_thread.t_ctl_waitq); wait_event(ll_capa_thread.t_ctl_waitq, - thread_is_stopped(&ll_capa_thread)); + thread_is_stopped(&ll_capa_thread)); } struct obd_capa *ll_osscapa_get(struct inode *inode, __u64 opc) @@ -360,7 +364,7 @@ struct obd_capa *ll_osscapa_get(struct inode *inode, __u64 opc) ocapa = NULL; if (atomic_read(&ll_capa_debug)) { - CERROR("no capability for "DFID" opc %#llx\n", + CERROR("no capability for " DFID " opc %#llx\n", PFID(&lli->lli_fid), opc); atomic_set(&ll_capa_debug, 0); } @@ -376,7 +380,7 @@ struct obd_capa *ll_mdscapa_get(struct inode *inode) struct ll_inode_info *lli = ll_i2info(inode); struct obd_capa *ocapa; - LASSERT(inode != NULL); + LASSERT(inode); if ((ll_i2sbi(inode)->ll_flags & LL_SBI_MDS_CAPA) == 0) return NULL; @@ -385,7 +389,7 @@ struct obd_capa *ll_mdscapa_get(struct inode *inode) ocapa = capa_get(lli->lli_mds_capa); spin_unlock(&capa_lock); if (!ocapa && atomic_read(&ll_capa_debug)) { - CERROR("no mds capability for "DFID"\n", PFID(&lli->lli_fid)); + CERROR("no mds capability for " DFID "\n", PFID(&lli->lli_fid)); atomic_set(&ll_capa_debug, 0); } @@ -447,7 +451,8 @@ static inline void inode_add_oss_capa(struct inode *inode, struct list_head *next = NULL; /* capa is sorted in lli_oss_capas so lookup can always find the - * latest one */ + * latest one + */ list_for_each_entry(tmp, &lli->lli_oss_capas, u.cli.lli_list) { if (cfs_time_after(ocapa->c_expiry, tmp->c_expiry)) { next = &tmp->u.cli.lli_list; @@ -537,7 +542,8 @@ static int ll_update_capa(struct obd_capa *ocapa, struct lustre_capa *capa) ll_capa_renewal_failed++; /* failed capa won't be renewed any longer, but if -EIO, - * client might be doing recovery, retry in 2 min. */ + * client might be doing recovery, retry in 2 min. + */ if (rc == -EIO && !capa_is_expired(ocapa)) { delay_capa_renew(ocapa, 120); DEBUG_CAPA(D_ERROR, &ocapa->c_capa, @@ -638,7 +644,7 @@ void ll_clear_inode_capas(struct inode *inode) ll_delete_capa(ocapa); list_for_each_entry_safe(ocapa, tmp, &lli->lli_oss_capas, - u.cli.lli_list) + u.cli.lli_list) ll_delete_capa(ocapa); spin_unlock(&capa_lock); } diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index ab4839cad939..55e2dc6c1fbf 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1150,6 +1150,8 @@ void ll_clear_inode(struct inode *inode) lli->lli_has_smd = false; } +#define TIMES_SET_FLAGS (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET) + static int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data, struct md_open_data **mod) { @@ -1354,11 +1356,8 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) if (!op_data) return -ENOMEM; - if (!S_ISDIR(inode->i_mode)) { - if (attr->ia_valid & ATTR_SIZE) - inode_dio_write_done(inode); + if (!S_ISDIR(inode->i_mode)) mutex_unlock(&inode->i_mutex); - } memcpy(&op_data->op_attr, attr, sizeof(*attr)); diff --git a/drivers/staging/lustre/lustre/llite/lloop.c b/drivers/staging/lustre/lustre/llite/lloop.c index cc00fd10fbcf..56938d2446bf 100644 --- a/drivers/staging/lustre/lustre/llite/lloop.c +++ b/drivers/staging/lustre/lustre/llite/lloop.c @@ -365,7 +365,7 @@ static void loop_make_request(struct request_queue *q, struct bio *old_bio) loop_add_bio(lo, old_bio); return; err: - cfs_bio_io_error(old_bio, old_bio->bi_iter.bi_size); + bio_io_error(old_bio); } @@ -376,7 +376,7 @@ static inline void loop_handle_bio(struct lloop_device *lo, struct bio *bio) while (bio) { struct bio *tmp = bio->bi_next; bio->bi_next = NULL; - cfs_bio_endio(bio, bio->bi_iter.bi_size, ret); + bio_endio(bio, ret); bio = tmp; } } diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 72ce6e72845f..05e7dc85989e 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -144,10 +144,9 @@ struct inode *ll_iget(struct super_block *sb, ino_t hash, static void ll_invalidate_negative_children(struct inode *dir) { struct dentry *dentry, *tmp_subdir; - struct ll_d_hlist_node *p; ll_lock_dcache(dir); - ll_d_hlist_for_each_entry(dentry, p, &dir->i_dentry, d_u.d_alias) { + hlist_for_each_entry(dentry, &dir->i_dentry, d_u.d_alias) { spin_lock(&dentry->d_lock); if (!list_empty(&dentry->d_subdirs)) { struct dentry *child; @@ -334,15 +333,14 @@ void ll_i2gids(__u32 *suppgids, struct inode *i1, struct inode *i2) static struct dentry *ll_find_alias(struct inode *inode, struct dentry *dentry) { struct dentry *alias, *discon_alias, *invalid_alias; - struct ll_d_hlist_node *p; - if (ll_d_hlist_empty(&inode->i_dentry)) + if (hlist_empty(&inode->i_dentry)) return NULL; discon_alias = invalid_alias = NULL; ll_lock_dcache(inode); - ll_d_hlist_for_each_entry(alias, p, &inode->i_dentry, d_u.d_alias) { + hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) { LASSERT(alias != dentry); spin_lock(&alias->d_lock); @@ -690,7 +688,7 @@ static struct inode *ll_create_node(struct inode *dir, struct lookup_intent *it) goto out; } - LASSERT(ll_d_hlist_empty(&inode->i_dentry)); + LASSERT(hlist_empty(&inode->i_dentry)); /* We asked for a lock on the directory, but were granted a * lock on the inode. Since we finally have an inode pointer, @@ -1008,7 +1006,7 @@ static int ll_unlink(struct inode *dir, struct dentry *dentry) return rc; } -static int ll_mkdir(struct inode *dir, struct dentry *dentry, ll_umode_t mode) +static int ll_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) { int err; diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 91bba79678cf..a659962e09c8 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -455,12 +455,11 @@ static void vvp_io_setattr_end(const struct lu_env *env, struct cl_io *io = ios->cis_io; struct inode *inode = ccc_object_inode(io->ci_obj); - if (cl_io_is_trunc(io)) { + if (cl_io_is_trunc(io)) /* Truncate in memory pages - they must be clean pages * because osc has already notified to destroy osc_extents. */ vvp_do_vmtruncate(inode, io->u.ci_setattr.sa_attr.lvb_size); - inode_dio_write_done(inode); - } + mutex_unlock(&inode->i_mutex); } diff --git a/drivers/staging/lustre/lustre/llite/vvp_page.c b/drivers/staging/lustre/lustre/llite/vvp_page.c index 954ed08c6af2..a3cf5ad20c60 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_page.c +++ b/drivers/staging/lustre/lustre/llite/vvp_page.c @@ -227,11 +227,16 @@ static int vvp_page_prep_write(const struct lu_env *env, struct cl_io *unused) { struct page *vmpage = cl2vm_page(slice); + struct cl_page *pg = slice->cpl_page; LASSERT(PageLocked(vmpage)); LASSERT(!PageDirty(vmpage)); - set_page_writeback(vmpage); + /* ll_writepage path is not a sync write, so need to set page writeback + * flag */ + if (!pg->cp_sync_io) + set_page_writeback(vmpage); + vvp_write_pending(cl2ccc(slice->cpl_obj), cl2ccc_page(slice)); return 0; @@ -298,9 +303,6 @@ static void vvp_page_completion_write(const struct lu_env *env, struct cl_page *pg = slice->cpl_page; struct page *vmpage = cp->cpg_page; - LASSERT(ergo(pg->cp_sync_io != NULL, PageLocked(vmpage))); - LASSERT(PageWriteback(vmpage)); - CL_PAGE_HEADER(D_PAGE, env, pg, "completing WRITE with %d\n", ioret); /* @@ -316,14 +318,19 @@ static void vvp_page_completion_write(const struct lu_env *env, cp->cpg_write_queued = 0; vvp_write_complete(cl2ccc(slice->cpl_obj), cp); - /* - * Only mark the page error only when it's an async write because - * applications won't wait for IO to finish. - */ - if (pg->cp_sync_io == NULL) + if (pg->cp_sync_io != NULL) { + LASSERT(PageLocked(vmpage)); + LASSERT(!PageWriteback(vmpage)); + } else { + LASSERT(PageWriteback(vmpage)); + /* + * Only mark the page error only when it's an async write + * because applications won't wait for IO to finish. + */ vvp_vmpage_error(ccc_object_inode(pg->cp_obj), vmpage, ioret); - end_page_writeback(vmpage); + end_page_writeback(vmpage); + } } /** diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 5f4c115f4ff4..c5c67d982ef2 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -1440,7 +1440,7 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len, __u32 *genp; len = 0; - if (obd_ioctl_getdata(&buf, &len, (void *)uarg)) + if (obd_ioctl_getdata(&buf, &len, uarg)) return -EINVAL; data = (struct obd_ioctl_data *)buf; @@ -1473,7 +1473,7 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len, *genp = lov->lov_tgts[i]->ltd_gen; } - if (copy_to_user((void *)uarg, buf, len)) + if (copy_to_user(uarg, buf, len)) rc = -EFAULT; obd_ioctl_freedata(buf, len); break; diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index d3234cb1ea22..1a850ea26849 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -286,7 +286,7 @@ static inline __u64 attr_pack(unsigned int ia_valid) sa_valid |= MDS_ATTR_KILL_SGID; if (ia_valid & ATTR_CTIME_SET) sa_valid |= MDS_ATTR_CTIME_SET; - if (ia_valid & ATTR_FROM_OPEN) + if (ia_valid & ATTR_OPEN) sa_valid |= MDS_ATTR_FROM_OPEN; if (ia_valid & ATTR_BLOCKS) sa_valid |= MDS_ATTR_BLOCKS; diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c index 562bd95bdcb9..019ee2f256aa 100644 --- a/drivers/staging/lustre/lustre/mgc/mgc_request.c +++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c @@ -1232,7 +1232,7 @@ static int mgc_apply_recover_logs(struct obd_device *mgc, pos += sprintf(obdname + pos, "-%s%04x", is_ost ? "OST" : "MDT", entry->mne_index); - cname = is_ost ? "osc" : "mdc", + cname = is_ost ? "osc" : "mdc"; pos += sprintf(obdname + pos, "-%s-%s", cname, inst); lustre_cfg_bufs_reset(&bufs, obdname); diff --git a/drivers/staging/lustre/lustre/obdclass/acl.c b/drivers/staging/lustre/lustre/obdclass/acl.c index bc3fc4780cb9..933456c502d1 100644 --- a/drivers/staging/lustre/lustre/obdclass/acl.c +++ b/drivers/staging/lustre/lustre/obdclass/acl.c @@ -104,11 +104,10 @@ static int lustre_posix_acl_xattr_reduce_space(posix_acl_xattr_header **header, if (unlikely(old_count <= new_count)) return old_size; - new = kzalloc(new_size, GFP_NOFS); + new = kmemdup(*header, new_size, GFP_NOFS); if (unlikely(new == NULL)) return -ENOMEM; - memcpy(new, *header, new_size); kfree(*header); *header = new; return new_size; @@ -125,11 +124,10 @@ static int lustre_ext_acl_xattr_reduce_space(ext_acl_xattr_header **header, if (unlikely(old_count <= ext_count)) return 0; - new = kzalloc(ext_size, GFP_NOFS); + new = kmemdup(*header, ext_size, GFP_NOFS); if (unlikely(new == NULL)) return -ENOMEM; - memcpy(new, *header, ext_size); kfree(*header); *header = new; return 0; diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c index 282ae734fba2..d5fb81f84cd4 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_page.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c @@ -51,13 +51,13 @@ static void cl_page_delete0(const struct lu_env *env, struct cl_page *pg, int radix); -# define PASSERT(env, page, expr) \ - do { \ - if (unlikely(!(expr))) { \ - CL_PAGE_DEBUG(D_ERROR, (env), (page), #expr "\n"); \ - LASSERT(0); \ - } \ - } while (0) +# define PASSERT(env, page, expr) \ + do { \ + if (unlikely(!(expr))) { \ + CL_PAGE_DEBUG(D_ERROR, (env), (page), #expr "\n"); \ + LASSERT(0); \ + } \ + } while (0) # define PINVRNT(env, page, exp) \ ((void)sizeof(env), (void)sizeof(page), (void)sizeof !!(exp)) @@ -169,6 +169,7 @@ int cl_page_gang_lookup(const struct lu_env *env, struct cl_object *obj, while ((nr = radix_tree_gang_lookup(&hdr->coh_tree, (void **)pvec, idx, CLT_PVEC_SIZE)) > 0) { int end_of_region = 0; + idx = pvec[nr - 1]->cp_index + 1; for (i = 0, j = 0; i < nr; ++i) { page = pvec[i]; @@ -286,6 +287,7 @@ static struct cl_page *cl_page_alloc(const struct lu_env *env, GFP_NOFS); if (page != NULL) { int result = 0; + atomic_set(&page->cp_ref, 1); if (type == CPT_CACHEABLE) /* for radix tree */ atomic_inc(&page->cp_ref); @@ -352,8 +354,10 @@ static struct cl_page *cl_page_find0(const struct lu_env *env, idx, PFID(&hdr->coh_lu.loh_fid), vmpage, vmpage->private, type); /* fast path. */ if (type == CPT_CACHEABLE) { - /* vmpage lock is used to protect the child/parent - * relationship */ + /* + * vmpage lock is used to protect the child/parent + * relationship + */ KLASSERT(PageLocked(vmpage)); /* * cl_vmpage_page() can be called here without any locks as @@ -372,9 +376,8 @@ static struct cl_page *cl_page_find0(const struct lu_env *env, idx) == page)); } - if (page != NULL) { + if (page != NULL) return page; - } /* allocate and initialize cl_page */ page = cl_page_alloc(env, o, idx, vmpage, type); @@ -1189,9 +1192,6 @@ int cl_page_prep(const struct lu_env *env, struct cl_io *io, if (result == 0) cl_page_io_start(env, pg, crt); - KLASSERT(ergo(crt == CRT_WRITE && pg->cp_type == CPT_CACHEABLE, - equi(result == 0, - PageWriteback(cl_page_vmpage(env, pg))))); CL_PAGE_HEADER(D_TRACE, env, pg, "%d %d\n", crt, result); return result; } diff --git a/drivers/staging/lustre/lustre/obdclass/debug.c b/drivers/staging/lustre/lustre/obdclass/debug.c index 9c934e6d2ea1..c61add46b426 100644 --- a/drivers/staging/lustre/lustre/obdclass/debug.c +++ b/drivers/staging/lustre/lustre/obdclass/debug.c @@ -40,7 +40,7 @@ #define DEBUG_SUBSYSTEM D_OTHER -#include <linux/unaligned/access_ok.h> +#include <asm/unaligned.h> #include "../include/obd_support.h" #include "../include/lustre_debug.h" diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index b618c0bd7e09..6218ef34ee80 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -385,7 +385,7 @@ static int obd_device_list_seq_show(struct seq_file *p, void *v) return 0; } -struct seq_operations obd_device_list_sops = { +static const struct seq_operations obd_device_list_sops = { .start = obd_device_list_seq_start, .stop = obd_device_list_seq_stop, .next = obd_device_list_seq_next, @@ -406,7 +406,7 @@ static int obd_device_list_open(struct inode *inode, struct file *file) return 0; } -struct file_operations obd_device_list_fops = { +static const struct file_operations obd_device_list_fops = { .owner = THIS_MODULE, .open = obd_device_list_open, .read = seq_read, diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index 4d9b6333eeae..8e472327c880 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -602,7 +602,7 @@ static struct lu_object *lu_object_new(const struct lu_env *env, struct lu_site_bkt_data *bkt; o = lu_object_alloc(env, dev, f, conf); - if (unlikely(IS_ERR(o))) + if (IS_ERR(o)) return o; hs = dev->ld_site->ls_obj_hash; @@ -666,7 +666,7 @@ static struct lu_object *lu_object_find_try(const struct lu_env *env, * operations, including fld queries, inode loading, etc. */ o = lu_object_alloc(env, dev, f, conf); - if (unlikely(IS_ERR(o))) + if (IS_ERR(o)) return o; LASSERT(lu_fid_eq(lu_object_fid(o), f)); @@ -674,7 +674,7 @@ static struct lu_object *lu_object_find_try(const struct lu_env *env, cfs_hash_bd_lock(hs, &bd, 1); shadow = htable_lookup(s, &bd, f, waiter, &version); - if (likely(IS_ERR(shadow) && PTR_ERR(shadow) == -ENOENT)) { + if (likely(PTR_ERR(shadow) == -ENOENT)) { struct lu_site_bkt_data *bkt; bkt = cfs_hash_bd_extra_get(hs, &bd); @@ -1558,7 +1558,7 @@ static int keys_fill(struct lu_context *ctx) LINVRNT(key->lct_index == i); value = key->lct_init(ctx, key); - if (unlikely(IS_ERR(value))) + if (IS_ERR(value)) return PTR_ERR(value); if (!(ctx->lc_tags & LCT_NOREF)) diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c index 3e0b8a4b6486..7c5bab377f5c 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c @@ -247,13 +247,13 @@ int lustre_start_mgc(struct super_block *sb) mutex_lock(&mgc_start_lock); len = strlen(LUSTRE_MGC_OBDNAME) + strlen(libcfs_nid2str(nid)) + 1; - mgcname = kzalloc(len, GFP_NOFS); - niduuid = kzalloc(len + 2, GFP_NOFS); + mgcname = kasprintf(GFP_NOFS, + "%s%s", LUSTRE_MGC_OBDNAME, libcfs_nid2str(nid)); + niduuid = kasprintf(GFP_NOFS, "%s_%x", mgcname, i); if (!mgcname || !niduuid) { rc = -ENOMEM; goto out_free; } - sprintf(mgcname, "%s%s", LUSTRE_MGC_OBDNAME, libcfs_nid2str(nid)); mgssec = lsi->lsi_lmd->lmd_mgssec ? lsi->lsi_lmd->lmd_mgssec : ""; @@ -326,7 +326,6 @@ int lustre_start_mgc(struct super_block *sb) /* Add the primary nids for the MGS */ i = 0; - sprintf(niduuid, "%s_%x", mgcname, i); if (IS_SERVER(lsi)) { ptr = lsi->lsi_lmd->lmd_mgs; if (IS_MGS(lsi)) { @@ -1120,10 +1119,9 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd) /* Remove leading /s from fsname */ while (*++s1 == '/') ; /* Freed in lustre_free_lsi */ - lmd->lmd_profile = kzalloc(strlen(s1) + 8, GFP_NOFS); + lmd->lmd_profile = kasprintf(GFP_NOFS, "%s-client", s1); if (!lmd->lmd_profile) return -ENOMEM; - sprintf(lmd->lmd_profile, "%s-client", s1); } /* Freed in lustre_free_lsi */ @@ -1281,7 +1279,7 @@ struct file_system_type lustre_fs_type = { .mount = lustre_mount, .kill_sb = lustre_kill_super, .fs_flags = FS_BINARY_MOUNTDATA | FS_REQUIRES_DEV | - FS_HAS_FIEMAP | FS_RENAME_DOES_D_MOVE, + FS_RENAME_DOES_D_MOVE, }; MODULE_ALIAS_FS("lustre"); diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index de6f795e05d1..27bd170c3a28 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -2139,7 +2139,7 @@ static struct obd_ops echo_client_obd_ops = { .o_disconnect = echo_client_disconnect }; -int echo_client_init(void) +static int echo_client_init(void) { int rc; @@ -2154,7 +2154,7 @@ int echo_client_init(void) return rc; } -void echo_client_exit(void) +static void echo_client_exit(void) { class_unregister_type(LUSTRE_ECHO_CLIENT_NAME); lu_kmem_fini(echo_caches); diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 96c80e9bf92d..12113dfd87b8 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -2665,7 +2665,7 @@ static int osc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, buf = NULL; len = 0; - if (obd_ioctl_getdata(&buf, &len, (void *)uarg)) { + if (obd_ioctl_getdata(&buf, &len, uarg)) { err = -EINVAL; goto out; } @@ -2695,7 +2695,7 @@ static int osc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, memcpy(data->ioc_inlbuf2, &obd->obd_uuid, sizeof(uuid)); - err = copy_to_user((void *)uarg, buf, len); + err = copy_to_user(uarg, buf, len); if (err) err = -EFAULT; obd_ioctl_freedata(buf, len); diff --git a/drivers/staging/lustre/lustre/ptlrpc/events.c b/drivers/staging/lustre/lustre/ptlrpc/events.c index 8cb1929fd31d..c8ef9e578263 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/events.c +++ b/drivers/staging/lustre/lustre/ptlrpc/events.c @@ -485,7 +485,7 @@ int ptlrpc_uuid_to_peer(struct obd_uuid *uuid, return rc; } -void ptlrpc_ni_fini(void) +static void ptlrpc_ni_fini(void) { wait_queue_head_t waitq; struct l_wait_info lwi; @@ -529,7 +529,7 @@ lnet_pid_t ptl_get_pid(void) return pid; } -int ptlrpc_ni_init(void) +static int ptlrpc_ni_init(void) { int rc; lnet_pid_t pid; diff --git a/drivers/staging/lustre/lustre/ptlrpc/pinger.c b/drivers/staging/lustre/lustre/ptlrpc/pinger.c index d05c37c1fd30..f8edb791a998 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pinger.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pinger.c @@ -318,8 +318,6 @@ int ptlrpc_start_pinger(void) strcpy(pinger_thread.t_name, "ll_ping"); - /* CLONE_VM and CLONE_FILES just avoid a needless copy, because we - * just drop the VM and FILES in cfs_daemonize_ctxt() right away. */ rc = PTR_ERR(kthread_run(ptlrpc_pinger_main, &pinger_thread, "%s", pinger_thread.t_name)); if (IS_ERR_VALUE(rc)) { diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index cf9477d4749b..003344ccfffc 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -43,7 +43,7 @@ #include "ptlrpc_internal.h" /* The following are visible and mutable through /sys/module/ptlrpc */ -int test_req_buffer_pressure = 0; +int test_req_buffer_pressure; module_param(test_req_buffer_pressure, int, 0444); MODULE_PARM_DESC(test_req_buffer_pressure, "set non-zero to put pressure on request buffer pools"); module_param(at_min, int, 0644); @@ -69,7 +69,7 @@ LIST_HEAD(ptlrpc_all_services); /** Used to protect the \e ptlrpc_all_services list */ struct mutex ptlrpc_all_services_mutex; -struct ptlrpc_request_buffer_desc * +static struct ptlrpc_request_buffer_desc * ptlrpc_alloc_rqbd(struct ptlrpc_service_part *svcpt) { struct ptlrpc_service *svc = svcpt->scp_service; @@ -101,7 +101,7 @@ ptlrpc_alloc_rqbd(struct ptlrpc_service_part *svcpt) return rqbd; } -void +static void ptlrpc_free_rqbd(struct ptlrpc_request_buffer_desc *rqbd) { struct ptlrpc_service_part *svcpt = rqbd->rqbd_svcpt; @@ -118,7 +118,7 @@ ptlrpc_free_rqbd(struct ptlrpc_request_buffer_desc *rqbd) kfree(rqbd); } -int +static int ptlrpc_grow_req_bufs(struct ptlrpc_service_part *svcpt, int post) { struct ptlrpc_service *svc = svcpt->scp_service; @@ -3052,7 +3052,7 @@ EXPORT_SYMBOL(ptlrpc_unregister_service); * Right now, it just checks to make sure that requests aren't languishing * in the queue. We'll use this health check to govern whether a node needs * to be shot, so it's intentionally non-aggressive. */ -int ptlrpc_svcpt_health_check(struct ptlrpc_service_part *svcpt) +static int ptlrpc_svcpt_health_check(struct ptlrpc_service_part *svcpt) { struct ptlrpc_request *request = NULL; struct timeval right_now; diff --git a/drivers/staging/most/Documentation/ABI/sysfs-class-most.txt b/drivers/staging/most/Documentation/ABI/sysfs-class-most.txt new file mode 100644 index 000000000000..380c137089d0 --- /dev/null +++ b/drivers/staging/most/Documentation/ABI/sysfs-class-most.txt @@ -0,0 +1,181 @@ +What: /sys/class/most/mostcore/aims +Date: June 2015 +KernelVersion: 4.3 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + List of AIMs that have been loaded. +Users: + +What: /sys/class/most/mostcore/aims/<aim>/add_link +Date: June 2015 +KernelVersion: 4.3 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to establish a connection of a channel and the + current AIM. +Users: + +What: /sys/class/most/mostcore/aims/<aim>/remove_link +Date: June 2015 +KernelVersion: 4.3 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is used to remove a connected channel from the + current AIM. +Users: + +What: /sys/class/most/mostcore/devices +Date: June 2015 +KernelVersion: 4.3 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + List of attached MOST interfaces. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/description +Date: June 2015 +KernelVersion: 4.3 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Provides information about the interface type and the physical + location of the device. Hardware attached via USB, for instance, + might return <usb_device 1-1.1:1.0> +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/interface +Date: June 2015 +KernelVersion: 4.3 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the type of peripherial interface the current device + uses. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/<channel>/ +Date: June 2015 +KernelVersion: 4.3 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + For every channel of the device a directory is created, whose + name is dictated by the HDM. This enables an application to + collect information about the channel's capabilities and + configure it. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/<channel>/available_datatypes +Date: June 2015 +KernelVersion: 4.3 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the data types the current channel can transport. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/<channel>/available_directions +Date: June 2015 +KernelVersion: 4.3 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the directions the current channel is capable of. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/<channel>/number_of_packet_buffers +Date: June 2015 +KernelVersion: 4.3 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the number of packet buffers the current channel can + handle. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/<channel>/number_of_stream_buffers +Date: June 2015 +KernelVersion: 4.3 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the number of streaming buffers the current channel can + handle. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/<channel>/size_of_packet_buffer +Date: June 2015 +KernelVersion: 4.3 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the size of a packet buffer the current channel can + handle. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/<channel>/size_of_stream_buffer +Date: June 2015 +KernelVersion: 4.3 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates the size of a streaming buffer the current channel can + handle. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/<channel>/set_number_of_buffers +Date: June 2015 +KernelVersion: 4.3 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is to configure the number of buffers of the current channel. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/<channel>/set_buffer_size +Date: June 2015 +KernelVersion: 4.3 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is to configure the size of a buffer of the current channel. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/<channel>/set_direction +Date: June 2015 +KernelVersion: 4.3 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is to configure the direction of the current channel. + The following strings will be accepted: + 'dir_tx', + 'dir_rx' +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/<channel>/set_datatype +Date: June 2015 +KernelVersion: 4.3 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is to configure the data type of the current channel. + The following strings will be accepted: + 'control', + 'async', + 'sync', + 'isoc_avp' +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/<channel>/set_subbuffer_size +Date: June 2015 +KernelVersion: 4.3 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is to configure the subbuffer size of the current channel. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/<channel>/set_packets_per_xact +Date: June 2015 +KernelVersion: 4.3 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + This is to configure the number of packets per transaction of + the current channel. This is only needed network interface + controller is attached via USB. +Users: + +What: /sys/class/most/mostcore/devices/<mdev>/<channel>/channel_starving +Date: June 2015 +KernelVersion: 4.3 +Contact: Christian Gromm <christian.gromm@microchip.com> +Description: + Indicates whether current channel ran out of buffers. +Users: diff --git a/drivers/staging/most/Documentation/driver_usage.txt b/drivers/staging/most/Documentation/driver_usage.txt new file mode 100644 index 000000000000..a4dc0c348fbc --- /dev/null +++ b/drivers/staging/most/Documentation/driver_usage.txt @@ -0,0 +1,180 @@ + + Section 1 Overview + +The Media Oriented Systems Transport (MOST) driver gives Linux applications +access a MOST network: The Automotive Information Backbone and the de-facto +standard for high-bandwidth automotive multimedia networking. + +MOST defines the protocol, hardware and software layers necessary to allow +for the efficient and low-cost transport of control, real-time and packet +data using a single medium (physical layer). Media currently in use are +fiber optics, unshielded twisted pair cables (UTP) and coax cables. MOST +also supports various speed grades up to 150 Mbps. +For more information on MOST, visit the MOST Cooperation website: +www.mostcooperation.com. + +Cars continue to evolve into sophisticated consumer electronics platforms, +increasing the demand for reliable and simple solutions to support audio, +video and data communications. MOST can be used to connect multiple +consumer devices via optical or electrical physical layers directly to one +another or in a network configuration. As a synchronous network, MOST +provides excellent Quality of Service and seamless connectivity for +audio/video streaming. Therefore, the driver perfectly fits to the mission +of Automotive Grade Linux to create open source software solutions for +automotive applications. + +The driver consists basically of three layers. The hardware layer, the +core layer and the application layer. The core layer consists of the core +module only. This module handles the communication flow through all three +layers, the configuration of the driver, the configuration interface +representation in sysfs, and the buffer management. +For each of the other two layers a selection of modules is provided. These +modules can arbitrarily be combined to meet the needs of the desired +system architecture. A module of the hardware layer is referred to as an +HDM (hardware dependent module). Each module of this layer handles exactly +one of the peripheral interfaces of a network interface controller (e.g. +USB, MediaLB, I2C). A module of the application layer is referred to as an +AIM (application interfacing module). The modules of this layer give access +to MOST via one the following ways: character devices, ALSA, Networking or +V4L2. + +To physically access MOST, an Intelligent Network Interface Controller +(INIC) is needed. For more information on available controllers visit: +www.microchip.com + + + + Section 1.1 Hardware Layer + +The hardware layer contains so called hardware dependent modules (HDM). For each +peripheral interface the hardware supports the driver has a suitable module +that handles the interface. + +The HDMs encapsulate the peripheral interface specific knowledge of the driver +and provides an easy way of extending the number of supported interfaces. +Currently the following HDMs are available: + + 1) MediaLB (DIM2) + Host wants to communicate with hardware via MediaLB. + + 2) I2C + Host wants to communicate with the hardware via I2C. + + 3) USB + Host wants to communicate with the hardware via USB. + + + Section 1.2 Core Layer + +The core layer contains the mostcore module only, which processes the driver +configuration via sysfs, buffer management and data forwarding. + + + + Section 1.2 Application Layer + +The application layer contains so called application interfacing modules (AIM). +Depending on how the driver should interface to the application, one or more +suitable modules can be selected. + +The AIMs encapsulate the application interface specific knowledge of the driver +and provides access to user space or other kernel subsystems. +Currently the following AIMs are available + + 1) Character Device + Applications can access the driver by means of character devices. + + 2) Networking + Standard networking applications (e.g. iperf) can by used to access + the driver via the networking subsystem. + + 3) Video4Linux (v4l2) + Standard video applications (e.g. VLC) can by used to access the + driver via the V4L subsystem. + + 4) Advanced Linux Sound Architecture (ALSA) + Standard sound applications (e.g. aplay, arecord, audacity) can by + used to access the driver via the ALSA subsystem. + + + + Section 2 Configuration + +See ABI/sysfs-class-most.txt + + + + Section 3 USB Padding + +When transceiving synchronous or isochronous data, the number of packets per USB +transaction and the sub-buffer size need to be configured. These values +are needed for the driver to process buffer padding, as expected by hardware, +which is for performance optimization purposes of the USB transmission. + +When transmitting synchronous data the allocated channel width needs to be +written to 'set_subbuffer_size'. Additionally, the number of MOST frames that +should travel to the host within one USB transaction need to be written to +'packets_per_xact'. + +Internally the synchronous threshold is calculated as follows: + + frame_size = set_subbuffer_size * packets_per_xact + +In case 'packets_per_xact' is set to 0xFF the maximum number of packets, +allocated within one MOST frame, is calculated that fit into _one_ 512 byte +USB full packet. + + frame_size = floor(MTU_USB / bandwidth_sync) * bandwidth_sync + +This frame_size is the number of synchronous data within an USB transaction, +which renders MTU_USB - frame_size bytes for padding. + +When transmitting isochronous AVP data the desired packet size needs to be +written to 'set_subbuffer_size' and hardware will always expect two isochronous +packets within one USB transaction. This renders + + MTU_USB - (2 * set_subbuffer_size) + +bytes for padding. + +Note that at least 2 times set_subbuffer_size bytes for isochronous data or +set_subbuffer_size times packts_per_xact bytes for synchronous data need to be +put in the transmission buffer and passed to the driver. + +Since HDMs are allowed to change a chosen configuration to best fit its +constraints, it is recommended to always double check the configuration and read +back the previously written files. + + + + Section 4 Routing Channels + +To connect a channel that has been configured as outlined above to an AIM and +make it accessible to user space applications, the attribute file 'add_link' is +used. To actually bind a channel to the AIM a string needs to be written to the +file that complies with the following syntax: + + "most_device:channel_name:link_name[.param]" + +The example above links the channel "channel_name" of the device "most_device" +to the AIM. In case the AIM interfaces the VFS this would also create a device +node "link_name" in the /dev directory. The parameter "param" is an AIM dependent +string, which can be omitted in case the used AIM does not make any use of it. + +Cdev AIM example: + $ echo "mdev0:ep_81:my_rx_channel" >add_link + $ echo "mdev0:ep_81" >add_link + + +Sound/ALSA AIM example: + +The sound/ALSA AIM needs an additional parameter to determine the audio resolution +that is going to be used. The following strings can be used: + + - "1x8" (Mono) + - "2x16" (16-bit stereo) + - "2x24" (24-bit stereo) + - "2x32" (32-bit stereo) + + $ echo "mdev0:ep_81:audio_rx.2x16" >add_link + $ echo "mdev0:ep_81" >add_link diff --git a/drivers/staging/most/Kconfig b/drivers/staging/most/Kconfig new file mode 100644 index 000000000000..d50de03de7b9 --- /dev/null +++ b/drivers/staging/most/Kconfig @@ -0,0 +1,30 @@ +menuconfig MOST + tristate "MOST driver" + select MOSTCORE + default n + ---help--- + This option allows you to enable support for MOST Network transceivers. + + If in doubt, say N here. + + + +if MOST + +source "drivers/staging/most/mostcore/Kconfig" + +source "drivers/staging/most/aim-cdev/Kconfig" + +source "drivers/staging/most/aim-network/Kconfig" + +source "drivers/staging/most/aim-sound/Kconfig" + +source "drivers/staging/most/aim-v4l2/Kconfig" + +source "drivers/staging/most/hdm-dim2/Kconfig" + +source "drivers/staging/most/hdm-i2c/Kconfig" + +source "drivers/staging/most/hdm-usb/Kconfig" + +endif diff --git a/drivers/staging/most/Makefile b/drivers/staging/most/Makefile new file mode 100644 index 000000000000..9ee981c7786b --- /dev/null +++ b/drivers/staging/most/Makefile @@ -0,0 +1,8 @@ +obj-$(CONFIG_MOSTCORE) += mostcore/ +obj-$(CONFIG_AIM_CDEV) += aim-cdev/ +obj-$(CONFIG_AIM_NETWORK) += aim-network/ +obj-$(CONFIG_AIM_SOUND) += aim-sound/ +obj-$(CONFIG_AIM_V4L2) += aim-v4l2/ +obj-$(CONFIG_HDM_DIM2) += hdm-dim2/ +obj-$(CONFIG_HDM_I2C) += hdm-i2c/ +obj-$(CONFIG_HDM_USB) += hdm-usb/ diff --git a/drivers/staging/most/TODO b/drivers/staging/most/TODO new file mode 100644 index 000000000000..4fa11a9d2cf7 --- /dev/null +++ b/drivers/staging/most/TODO @@ -0,0 +1,8 @@ +* Get through code review with Greg Kroah-Hartman + +Contact: +To: +Christian Gromm <christian.gromm@microchip.com> +Cc: +Michael Fabry <Michael.Fabry@microchip.com> +Christian Gromm <chris@engineersdelight.de> diff --git a/drivers/staging/most/aim-cdev/Kconfig b/drivers/staging/most/aim-cdev/Kconfig new file mode 100644 index 000000000000..3c59f1bac127 --- /dev/null +++ b/drivers/staging/most/aim-cdev/Kconfig @@ -0,0 +1,12 @@ +# +# MOST Cdev configuration +# + +config AIM_CDEV + tristate "Cdev AIM" + + ---help--- + Say Y here if you want to commumicate via character devices. + + To compile this driver as a module, choose M here: the + module will be called aim_cdev.
\ No newline at end of file diff --git a/drivers/staging/most/aim-cdev/Makefile b/drivers/staging/most/aim-cdev/Makefile new file mode 100644 index 000000000000..0bcc6c637b75 --- /dev/null +++ b/drivers/staging/most/aim-cdev/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_AIM_CDEV) += aim_cdev.o + +aim_cdev-objs := cdev.o +ccflags-y += -Idrivers/staging/most/mostcore/
\ No newline at end of file diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c new file mode 100644 index 000000000000..252a17cf153c --- /dev/null +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -0,0 +1,528 @@ +/* + * cdev.c - Application interfacing module for character devices + * + * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This file is licensed under GPLv2. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/fs.h> +#include <linux/slab.h> +#include <linux/device.h> +#include <linux/cdev.h> +#include <linux/kfifo.h> +#include <linux/uaccess.h> +#include <linux/idr.h> +#include "mostcore.h" + +static dev_t aim_devno; +static struct class *aim_class; +static struct ida minor_id; +static unsigned int major; + +struct aim_channel { + wait_queue_head_t wq; + struct cdev cdev; + struct device *dev; + struct mutex io_mutex; + struct most_interface *iface; + struct most_channel_config *cfg; + unsigned int channel_id; + dev_t devno; + bool keep_mbo; + unsigned int mbo_offs; + struct mbo *stacked_mbo; + DECLARE_KFIFO_PTR(fifo, typeof(struct mbo *)); + atomic_t access_ref; + struct list_head list; +}; +#define to_channel(d) container_of(d, struct aim_channel, cdev) +static struct list_head channel_list; +static spinlock_t ch_list_lock; + + +struct aim_channel *get_channel(struct most_interface *iface, int id) +{ + struct aim_channel *channel, *tmp; + unsigned long flags; + int found_channel = 0; + + spin_lock_irqsave(&ch_list_lock, flags); + list_for_each_entry_safe(channel, tmp, &channel_list, list) { + if ((channel->iface == iface) && (channel->channel_id == id)) { + found_channel = 1; + break; + } + } + spin_unlock_irqrestore(&ch_list_lock, flags); + if (!found_channel) + return NULL; + return channel; +} + +/** + * aim_open - implements the syscall to open the device + * @inode: inode pointer + * @filp: file pointer + * + * This stores the channel pointer in the private data field of + * the file structure and activates the channel within the core. + */ +static int aim_open(struct inode *inode, struct file *filp) +{ + struct aim_channel *channel; + int ret; + + channel = to_channel(inode->i_cdev); + filp->private_data = channel; + + if (((channel->cfg->direction == MOST_CH_RX) && + ((filp->f_flags & O_ACCMODE) != O_RDONLY)) + || ((channel->cfg->direction == MOST_CH_TX) && + ((filp->f_flags & O_ACCMODE) != O_WRONLY))) { + pr_info("WARN: Access flags mismatch\n"); + return -EACCES; + } + if (!atomic_inc_and_test(&channel->access_ref)) { + pr_info("WARN: Device is busy\n"); + atomic_dec(&channel->access_ref); + return -EBUSY; + } + + ret = most_start_channel(channel->iface, channel->channel_id); + if (ret) + atomic_dec(&channel->access_ref); + return ret; +} + +/** + * aim_close - implements the syscall to close the device + * @inode: inode pointer + * @filp: file pointer + * + * This stops the channel within the core. + */ +static int aim_close(struct inode *inode, struct file *filp) +{ + int ret; + struct mbo *mbo; + struct aim_channel *channel = to_channel(inode->i_cdev); + + mutex_lock(&channel->io_mutex); + if (!channel->dev) { + mutex_unlock(&channel->io_mutex); + atomic_dec(&channel->access_ref); + device_destroy(aim_class, channel->devno); + cdev_del(&channel->cdev); + kfifo_free(&channel->fifo); + list_del(&channel->list); + ida_simple_remove(&minor_id, MINOR(channel->devno)); + wake_up_interruptible(&channel->wq); + kfree(channel); + return 0; + } + mutex_unlock(&channel->io_mutex); + + while (0 != kfifo_out((struct kfifo *)&channel->fifo, &mbo, 1)) + most_put_mbo(mbo); + if (channel->keep_mbo == true) + most_put_mbo(channel->stacked_mbo); + ret = most_stop_channel(channel->iface, channel->channel_id); + atomic_dec(&channel->access_ref); + wake_up_interruptible(&channel->wq); + return ret; +} + +/** + * aim_write - implements the syscall to write to the device + * @filp: file pointer + * @buf: pointer to user buffer + * @count: number of bytes to write + * @offset: offset from where to start writing + */ +static ssize_t aim_write(struct file *filp, const char __user *buf, + size_t count, loff_t *offset) +{ + int ret, err; + size_t actual_len = 0; + size_t max_len = 0; + ssize_t retval; + struct mbo *mbo; + struct aim_channel *channel = filp->private_data; + + mutex_lock(&channel->io_mutex); + if (unlikely(!channel->dev)) { + mutex_unlock(&channel->io_mutex); + return -EPIPE; + } + mutex_unlock(&channel->io_mutex); + + mbo = most_get_mbo(channel->iface, channel->channel_id); + + if (!mbo && channel->dev) { + if ((filp->f_flags & O_NONBLOCK)) + return -EAGAIN; + if (wait_event_interruptible( + channel->wq, + (mbo = most_get_mbo(channel->iface, + channel->channel_id)) || + (channel->dev == NULL))) + return -ERESTARTSYS; + } + + mutex_lock(&channel->io_mutex); + if (unlikely(!channel->dev)) { + mutex_unlock(&channel->io_mutex); + err = -EPIPE; + goto error; + } + mutex_unlock(&channel->io_mutex); + + max_len = channel->cfg->buffer_size; + actual_len = min(count, max_len); + mbo->buffer_length = actual_len; + + retval = copy_from_user(mbo->virt_address, buf, mbo->buffer_length); + if (retval) { + err = -EIO; + goto error; + } + + ret = most_submit_mbo(mbo); + if (ret) { + pr_info("submitting MBO to core failed\n"); + err = ret; + goto error; + } + return actual_len - retval; +error: + if (mbo) + most_put_mbo(mbo); + return err; +} + +/** + * aim_read - implements the syscall to read from the device + * @filp: file pointer + * @buf: pointer to user buffer + * @count: number of bytes to read + * @offset: offset from where to start reading + */ +static ssize_t +aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) +{ + ssize_t retval; + size_t not_copied, proc_len; + struct mbo *mbo; + struct aim_channel *channel = filp->private_data; + + if (channel->keep_mbo == true) { + mbo = channel->stacked_mbo; + channel->keep_mbo = false; + goto start_copy; + } + while ((0 == kfifo_out(&channel->fifo, &mbo, 1)) + && (channel->dev != NULL)) { + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + if (wait_event_interruptible(channel->wq, + (!kfifo_is_empty(&channel->fifo) || + (channel->dev == NULL)))) + return -ERESTARTSYS; + } + +start_copy: + /* make sure we don't submit to gone devices */ + mutex_lock(&channel->io_mutex); + if (unlikely(!channel->dev)) { + mutex_unlock(&channel->io_mutex); + return -EIO; + } + + if (count < mbo->processed_length) + channel->keep_mbo = true; + + proc_len = min((int)count, + (int)(mbo->processed_length - channel->mbo_offs)); + + not_copied = copy_to_user(buf, + mbo->virt_address + channel->mbo_offs, + proc_len); + + retval = not_copied ? proc_len - not_copied : proc_len; + + if (channel->keep_mbo == true) { + channel->mbo_offs = retval; + channel->stacked_mbo = mbo; + } else { + most_put_mbo(mbo); + channel->mbo_offs = 0; + } + mutex_unlock(&channel->io_mutex); + return retval; +} + +/** + * Initialization of struct file_operations + */ +static const struct file_operations channel_fops = { + .owner = THIS_MODULE, + .read = aim_read, + .write = aim_write, + .open = aim_open, + .release = aim_close, +}; + +/** + * aim_disconnect_channel - disconnect a channel + * @iface: pointer to interface instance + * @channel_id: channel index + * + * This frees allocated memory and removes the cdev that represents this + * channel in user space. + */ +int aim_disconnect_channel(struct most_interface *iface, int channel_id) +{ + struct aim_channel *channel; + unsigned long flags; + + if (!iface) { + pr_info("Bad interface pointer\n"); + return -EINVAL; + } + + channel = get_channel(iface, channel_id); + if (channel == NULL) + return -ENXIO; + + mutex_lock(&channel->io_mutex); + channel->dev = NULL; + mutex_unlock(&channel->io_mutex); + + if (atomic_read(&channel->access_ref)) { + device_destroy(aim_class, channel->devno); + cdev_del(&channel->cdev); + kfifo_free(&channel->fifo); + ida_simple_remove(&minor_id, MINOR(channel->devno)); + spin_lock_irqsave(&ch_list_lock, flags); + list_del(&channel->list); + spin_unlock_irqrestore(&ch_list_lock, flags); + kfree(channel); + } else { + wake_up_interruptible(&channel->wq); + } + return 0; +} + +/** + * aim_rx_completion - completion handler for rx channels + * @mbo: pointer to buffer object that has completed + * + * This searches for the channel linked to this MBO and stores it in the local + * fifo buffer. + */ +int aim_rx_completion(struct mbo *mbo) +{ + struct aim_channel *channel; + + if (!mbo) + return -EINVAL; + + channel = get_channel(mbo->ifp, mbo->hdm_channel_id); + if (channel == NULL) + return -ENXIO; + + kfifo_in(&channel->fifo, &mbo, 1); +#ifdef DEBUG_MESG + if (kfifo_is_full(&channel->fifo)) + pr_info("WARN: Fifo is full\n"); +#endif + wake_up_interruptible(&channel->wq); + return 0; +} + +/** + * aim_tx_completion - completion handler for tx channels + * @iface: pointer to interface instance + * @channel_id: channel index/ID + * + * This wakes sleeping processes in the wait-queue. + */ +int aim_tx_completion(struct most_interface *iface, int channel_id) +{ + struct aim_channel *channel; + + if (!iface) { + pr_info("Bad interface pointer\n"); + return -EINVAL; + } + if ((channel_id < 0) || (channel_id >= iface->num_channels)) { + pr_info("Channel ID out of range\n"); + return -EINVAL; + } + + channel = get_channel(iface, channel_id); + if (channel == NULL) + return -ENXIO; + wake_up_interruptible(&channel->wq); + return 0; +} + +struct most_aim cdev_aim; + +/** + * aim_probe - probe function of the driver module + * @iface: pointer to interface instance + * @channel_id: channel index/ID + * @cfg: pointer to actual channel configuration + * @parent: pointer to kobject (needed for sysfs hook-up) + * @name: name of the device to be created + * + * This allocates achannel object and creates the device node in /dev + * + * Returns 0 on success or error code otherwise. + */ +int aim_probe(struct most_interface *iface, int channel_id, + struct most_channel_config *cfg, + struct kobject *parent, char *name) +{ + struct aim_channel *channel; + unsigned long cl_flags; + int retval; + int current_minor; + + if ((!iface) || (!cfg) || (!parent) || (!name)) { + pr_info("Probing AIM with bad arguments"); + return -EINVAL; + } + channel = get_channel(iface, channel_id); + if (channel) + return -EEXIST; + + current_minor = ida_simple_get(&minor_id, 0, 0, GFP_KERNEL); + if (current_minor < 0) + return current_minor; + + channel = kzalloc(sizeof(*channel), GFP_KERNEL); + if (!channel) { + pr_info("failed to alloc channel object\n"); + retval = -ENOMEM; + goto error_alloc_channel; + } + + channel->devno = MKDEV(major, current_minor); + cdev_init(&channel->cdev, &channel_fops); + channel->cdev.owner = THIS_MODULE; + cdev_add(&channel->cdev, channel->devno, 1); + channel->iface = iface; + channel->cfg = cfg; + channel->channel_id = channel_id; + channel->mbo_offs = 0; + atomic_set(&channel->access_ref, -1); + INIT_KFIFO(channel->fifo); + retval = kfifo_alloc(&channel->fifo, cfg->num_buffers, GFP_KERNEL); + if (retval) { + pr_info("failed to alloc channel kfifo"); + goto error_alloc_kfifo; + } + init_waitqueue_head(&channel->wq); + mutex_init(&channel->io_mutex); + spin_lock_irqsave(&ch_list_lock, cl_flags); + list_add_tail(&channel->list, &channel_list); + spin_unlock_irqrestore(&ch_list_lock, cl_flags); + channel->dev = device_create(aim_class, + NULL, + channel->devno, + NULL, + "%s", name); + + retval = IS_ERR(channel->dev); + if (retval) { + pr_info("failed to create new device node %s\n", name); + goto error_create_device; + } + kobject_uevent(&channel->dev->kobj, KOBJ_ADD); + return 0; + +error_create_device: + kfifo_free(&channel->fifo); + list_del(&channel->list); +error_alloc_kfifo: + cdev_del(&channel->cdev); + kfree(channel); +error_alloc_channel: + ida_simple_remove(&minor_id, current_minor); + return retval; +} + +struct most_aim cdev_aim = { + .name = "cdev", + .probe_channel = aim_probe, + .disconnect_channel = aim_disconnect_channel, + .rx_completion = aim_rx_completion, + .tx_completion = aim_tx_completion, +}; + +static int __init mod_init(void) +{ + pr_info("init()\n"); + + INIT_LIST_HEAD(&channel_list); + spin_lock_init(&ch_list_lock); + ida_init(&minor_id); + + if (alloc_chrdev_region(&aim_devno, 0, 50, "cdev") < 0) + return -EIO; + major = MAJOR(aim_devno); + + aim_class = class_create(THIS_MODULE, "most_cdev_aim"); + if (IS_ERR(aim_class)) { + pr_err("no udev support\n"); + goto free_cdev; + } + + if (most_register_aim(&cdev_aim)) + goto dest_class; + return 0; + +dest_class: + class_destroy(aim_class); +free_cdev: + unregister_chrdev_region(aim_devno, 1); + return -EIO; +} + +static void __exit mod_exit(void) +{ + struct aim_channel *channel, *tmp; + + pr_info("exit module\n"); + + most_deregister_aim(&cdev_aim); + + list_for_each_entry_safe(channel, tmp, &channel_list, list) { + device_destroy(aim_class, channel->devno); + cdev_del(&channel->cdev); + kfifo_free(&channel->fifo); + list_del(&channel->list); + ida_simple_remove(&minor_id, MINOR(channel->devno)); + kfree(channel); + } + class_destroy(aim_class); + unregister_chrdev_region(aim_devno, 1); + ida_destroy(&minor_id); +} + +module_init(mod_init); +module_exit(mod_exit); +MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("character device AIM for mostcore"); diff --git a/drivers/staging/most/aim-network/Kconfig b/drivers/staging/most/aim-network/Kconfig new file mode 100644 index 000000000000..4c66b24cf73c --- /dev/null +++ b/drivers/staging/most/aim-network/Kconfig @@ -0,0 +1,13 @@ +# +# MOST Networking configuration +# + +config AIM_NETWORK + tristate "Networking AIM" + depends on NET + + ---help--- + Say Y here if you want to commumicate via a networking device. + + To compile this driver as a module, choose M here: the + module will be called aim_network. diff --git a/drivers/staging/most/aim-network/Makefile b/drivers/staging/most/aim-network/Makefile new file mode 100644 index 000000000000..840c1dd94873 --- /dev/null +++ b/drivers/staging/most/aim-network/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_AIM_NETWORK) += aim_network.o + +aim_network-objs := networking.o +ccflags-y += -Idrivers/staging/most/mostcore/ diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c new file mode 100644 index 000000000000..c8ab2399faad --- /dev/null +++ b/drivers/staging/most/aim-network/networking.c @@ -0,0 +1,567 @@ +/* + * Networking AIM - Networking Application Interface Module for MostCore + * + * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This file is licensed under GPLv2. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/list.h> +#include <linux/wait.h> +#include <linux/kobject.h> +#include "mostcore.h" +#include "networking.h" + + +#define MEP_HDR_LEN 8 +#define MDP_HDR_LEN 16 +#define MAMAC_DATA_LEN (1024 - MDP_HDR_LEN) + +#define PMHL 5 + +#define PMS_TELID_UNSEGM_MAMAC 0x0A +#define PMS_FIFONO_MDP 0x01 +#define PMS_FIFONO_MEP 0x04 +#define PMS_MSGTYPE_DATA 0x04 +#define PMS_DEF_PRIO 0 +#define MEP_DEF_RETRY 15 + +#define PMS_FIFONO_MASK 0x07 +#define PMS_FIFONO_SHIFT 3 +#define PMS_RETRY_SHIFT 4 +#define PMS_TELID_MASK 0x0F +#define PMS_TELID_SHIFT 4 + +#define HB(value) ((u8)((u16)(value) >> 8)) +#define LB(value) ((u8)(value)) + + + +#define EXTRACT_BIT_SET(bitset_name, value) \ + (((value) >> bitset_name##_SHIFT) & bitset_name##_MASK) + +#define PMS_IS_MEP(buf, len) \ + ((len) > MEP_HDR_LEN && \ + EXTRACT_BIT_SET(PMS_FIFONO, (buf)[3]) == PMS_FIFONO_MEP) + +#define PMS_IS_MAMAC(buf, len) \ + ((len) > MDP_HDR_LEN && \ + EXTRACT_BIT_SET(PMS_FIFONO, (buf)[3]) == PMS_FIFONO_MDP && \ + EXTRACT_BIT_SET(PMS_TELID, (buf)[14]) == PMS_TELID_UNSEGM_MAMAC) + +struct net_dev_channel { + bool linked; + int ch_id; +}; + +struct net_dev_context { + struct most_interface *iface; + bool channels_opened; + bool is_mamac; + unsigned char link_stat; + struct net_device *dev; + struct net_dev_channel rx; + struct net_dev_channel tx; + struct list_head list; +}; + +static struct list_head net_devices = LIST_HEAD_INIT(net_devices); +static struct spinlock list_lock; +static struct most_aim aim; + + +static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo) +{ + u8 *buff = mbo->virt_address; + const u8 broadcast[] = { 0x03, 0xFF }; + const u8 *dest_addr = skb->data + 4; + const u8 *eth_type = skb->data + 12; + unsigned int payload_len = skb->len - ETH_HLEN; + unsigned int mdp_len = payload_len + MDP_HDR_LEN; + + if (mbo->buffer_length < mdp_len) { + pr_err("drop: too small buffer! (%d for %d)\n", + mbo->buffer_length, mdp_len); + return -EINVAL; + } + + if (skb->len < ETH_HLEN) { + pr_err("drop: too small packet! (%d)\n", skb->len); + return -EINVAL; + } + + if (dest_addr[0] == 0xFF && dest_addr[1] == 0xFF) + dest_addr = broadcast; + + *buff++ = HB(mdp_len - 2); + *buff++ = LB(mdp_len - 2); + + *buff++ = PMHL; + *buff++ = (PMS_FIFONO_MDP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA; + *buff++ = PMS_DEF_PRIO; + *buff++ = dest_addr[0]; + *buff++ = dest_addr[1]; + *buff++ = 0x00; + + *buff++ = HB(payload_len + 6); + *buff++ = LB(payload_len + 6); + + /* end of FPH here */ + + *buff++ = eth_type[0]; + *buff++ = eth_type[1]; + *buff++ = 0; + *buff++ = 0; + + *buff++ = PMS_TELID_UNSEGM_MAMAC << 4 | HB(payload_len); + *buff++ = LB(payload_len); + + memcpy(buff, skb->data + ETH_HLEN, payload_len); + mbo->buffer_length = mdp_len; + return 0; +} + +static int skb_to_mep(const struct sk_buff *skb, struct mbo *mbo) +{ + u8 *buff = mbo->virt_address; + unsigned int mep_len = skb->len + MEP_HDR_LEN; + + if (mbo->buffer_length < mep_len) { + pr_err("drop: too small buffer! (%d for %d)\n", + mbo->buffer_length, mep_len); + return -EINVAL; + } + + *buff++ = HB(mep_len - 2); + *buff++ = LB(mep_len - 2); + + *buff++ = PMHL; + *buff++ = (PMS_FIFONO_MEP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA; + *buff++ = (MEP_DEF_RETRY << PMS_RETRY_SHIFT) | PMS_DEF_PRIO; + *buff++ = 0; + *buff++ = 0; + *buff++ = 0; + + memcpy(buff, skb->data, skb->len); + mbo->buffer_length = mep_len; + return 0; +} + +static int most_nd_set_mac_address(struct net_device *dev, void *p) +{ + struct net_dev_context *nd = dev->ml_priv; + int err = eth_mac_addr(dev, p); + + if (err) + return err; + + BUG_ON(nd->dev != dev); + + nd->is_mamac = + (dev->dev_addr[0] == 0 && dev->dev_addr[1] == 0 && + dev->dev_addr[2] == 0 && dev->dev_addr[3] == 0); + + /* + * Set default MTU for the given packet type. + * It is still possible to change MTU using ip tools afterwards. + */ + dev->mtu = nd->is_mamac ? MAMAC_DATA_LEN : ETH_DATA_LEN; + + return 0; +} + +static int most_nd_open(struct net_device *dev) +{ + struct net_dev_context *nd = dev->ml_priv; + + pr_info("open net device %s\n", dev->name); + + BUG_ON(nd->dev != dev); + + if (nd->channels_opened) + return -EFAULT; + + BUG_ON(!nd->tx.linked || !nd->rx.linked); + + if (most_start_channel(nd->iface, nd->rx.ch_id)) { + pr_err("most_start_channel() failed\n"); + return -EBUSY; + } + + if (most_start_channel(nd->iface, nd->tx.ch_id)) { + pr_err("most_start_channel() failed\n"); + most_stop_channel(nd->iface, nd->rx.ch_id); + return -EBUSY; + } + + nd->channels_opened = true; + + if (nd->is_mamac) { + nd->link_stat = 1; + netif_wake_queue(dev); + } else { + nd->iface->request_netinfo(nd->iface, nd->tx.ch_id); + } + + return 0; +} + +static int most_nd_stop(struct net_device *dev) +{ + struct net_dev_context *nd = dev->ml_priv; + + pr_info("stop net device %s\n", dev->name); + + BUG_ON(nd->dev != dev); + netif_stop_queue(dev); + + if (nd->channels_opened) { + most_stop_channel(nd->iface, nd->rx.ch_id); + most_stop_channel(nd->iface, nd->tx.ch_id); + nd->channels_opened = false; + } + + return 0; +} + +static netdev_tx_t most_nd_start_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct net_dev_context *nd = dev->ml_priv; + struct mbo *mbo; + int ret; + + BUG_ON(nd->dev != dev); + + mbo = most_get_mbo(nd->iface, nd->tx.ch_id); + + if (!mbo) { + netif_stop_queue(dev); + dev->stats.tx_fifo_errors++; + return NETDEV_TX_BUSY; + } + + if (nd->is_mamac) + ret = skb_to_mamac(skb, mbo); + else + ret = skb_to_mep(skb, mbo); + + if (ret) { + most_put_mbo(mbo); + dev->stats.tx_dropped++; + kfree_skb(skb); + return NETDEV_TX_OK; + } + + most_submit_mbo(mbo); + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; + kfree_skb(skb); + return NETDEV_TX_OK; +} + +static const struct net_device_ops most_nd_ops = { + .ndo_open = most_nd_open, + .ndo_stop = most_nd_stop, + .ndo_start_xmit = most_nd_start_xmit, + .ndo_set_mac_address = most_nd_set_mac_address, +}; + +static void most_nd_setup(struct net_device *dev) +{ + pr_info("setup net device %s\n", dev->name); + ether_setup(dev); + dev->netdev_ops = &most_nd_ops; +} + +static void most_net_rm_netdev_safe(struct net_dev_context *nd) +{ + if (!nd->dev) + return; + + pr_info("remove net device %p\n", nd->dev); + + unregister_netdev(nd->dev); + free_netdev(nd->dev); + nd->dev = 0; +} + +static struct net_dev_context *get_net_dev_context( + struct most_interface *iface) +{ + struct net_dev_context *nd, *tmp; + + spin_lock(&list_lock); + list_for_each_entry_safe(nd, tmp, &net_devices, list) { + if (nd->iface == iface) { + spin_unlock(&list_lock); + return nd; + } + } + spin_unlock(&list_lock); + return NULL; +} + +static int aim_probe_channel(struct most_interface *iface, int channel_idx, + struct most_channel_config *ccfg, + struct kobject *parent, char *name) +{ + struct net_dev_context *nd; + struct net_dev_channel *ch; + + if (!iface) + return -EINVAL; + + if (ccfg->data_type != MOST_CH_ASYNC) + return -EINVAL; + + nd = get_net_dev_context(iface); + + if (!nd) { + nd = kzalloc(sizeof(*nd), GFP_KERNEL); + if (!nd) + return -ENOMEM; + + nd->iface = iface; + + spin_lock(&list_lock); + list_add(&nd->list, &net_devices); + spin_unlock(&list_lock); + } + + ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx; + if (ch->linked) { + pr_err("only one channel per instance & direction allowed\n"); + return -EINVAL; + } + + if (nd->tx.linked || nd->rx.linked) { + struct net_device *dev = + alloc_netdev(0, "meth%d", NET_NAME_UNKNOWN, most_nd_setup); + + if (!dev) { + pr_err("no memory for net_device\n"); + return -ENOMEM; + } + + nd->dev = dev; + + dev->ml_priv = nd; + if (register_netdev(dev)) { + pr_err("registering net device failed\n"); + free_netdev(dev); + return -EINVAL; + } + } + + ch->ch_id = channel_idx; + ch->linked = true; + + return 0; +} + +static int aim_disconnect_channel(struct most_interface *iface, + int channel_idx) +{ + struct net_dev_context *nd; + struct net_dev_channel *ch; + + nd = get_net_dev_context(iface); + if (!nd) + return -EINVAL; + + if (nd->rx.linked && channel_idx == nd->rx.ch_id) + ch = &nd->rx; + else if (nd->tx.linked && channel_idx == nd->tx.ch_id) + ch = &nd->tx; + else + return -EINVAL; + + ch->linked = false; + + /* + * do not call most_stop_channel() here, because channels are + * going to be closed in ndo_stop() after unregister_netdev() + */ + most_net_rm_netdev_safe(nd); + + if (!nd->rx.linked && !nd->tx.linked) { + spin_lock(&list_lock); + list_del(&nd->list); + spin_unlock(&list_lock); + kfree(nd); + } + + return 0; +} + +static int aim_resume_tx_channel(struct most_interface *iface, + int channel_idx) +{ + struct net_dev_context *nd; + + nd = get_net_dev_context(iface); + if (!nd || !nd->channels_opened || nd->tx.ch_id != channel_idx) + return 0; + + if (!nd->dev) + return 0; + + netif_wake_queue(nd->dev); + return 0; +} + +static int aim_rx_data(struct mbo *mbo) +{ + const u32 zero = 0; + struct net_dev_context *nd; + char *buf = mbo->virt_address; + uint32_t len = mbo->processed_length; + struct sk_buff *skb; + struct net_device *dev; + + nd = get_net_dev_context(mbo->ifp); + if (!nd || !nd->channels_opened || nd->rx.ch_id != mbo->hdm_channel_id) + return -EIO; + + dev = nd->dev; + if (!dev) { + pr_err_once("drop packet: missing net_device\n"); + return -EIO; + } + + if (nd->is_mamac) { + if (!PMS_IS_MAMAC(buf, len)) + return -EIO; + + skb = dev_alloc_skb(len - MDP_HDR_LEN + 2 * ETH_ALEN + 2); + } else { + if (!PMS_IS_MEP(buf, len)) + return -EIO; + + skb = dev_alloc_skb(len - MEP_HDR_LEN); + } + + if (!skb) { + dev->stats.rx_dropped++; + pr_err_once("drop packet: no memory for skb\n"); + goto out; + } + + skb->dev = dev; + + if (nd->is_mamac) { + /* dest */ + memcpy(skb_put(skb, ETH_ALEN), dev->dev_addr, ETH_ALEN); + + /* src */ + memcpy(skb_put(skb, 4), &zero, 4); + memcpy(skb_put(skb, 2), buf + 5, 2); + + /* eth type */ + memcpy(skb_put(skb, 2), buf + 10, 2); + + buf += MDP_HDR_LEN; + len -= MDP_HDR_LEN; + } else { + buf += MEP_HDR_LEN; + len -= MEP_HDR_LEN; + } + + memcpy(skb_put(skb, len), buf, len); + skb->protocol = eth_type_trans(skb, dev); + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; + netif_rx(skb); + +out: + most_put_mbo(mbo); + return 0; +} + +static int __init most_net_init(void) +{ + pr_info("most_net_init()\n"); + spin_lock_init(&list_lock); + aim.name = "networking"; + aim.probe_channel = aim_probe_channel; + aim.disconnect_channel = aim_disconnect_channel; + aim.tx_completion = aim_resume_tx_channel; + aim.rx_completion = aim_rx_data; + return most_register_aim(&aim); +} + +static void __exit most_net_exit(void) +{ + struct net_dev_context *nd, *tmp; + + spin_lock(&list_lock); + list_for_each_entry_safe(nd, tmp, &net_devices, list) { + list_del(&nd->list); + spin_unlock(&list_lock); + /* + * do not call most_stop_channel() here, because channels are + * going to be closed in ndo_stop() after unregister_netdev() + */ + most_net_rm_netdev_safe(nd); + kfree(nd); + spin_lock(&list_lock); + } + spin_unlock(&list_lock); + + most_deregister_aim(&aim); + pr_info("most_net_exit()\n"); +} + +/** + * most_deliver_netinfo - callback for HDM to be informed about HW's MAC + * @param iface - most interface instance + * @param link_stat - link status + * @param mac_addr - MAC address + */ +void most_deliver_netinfo(struct most_interface *iface, + unsigned char link_stat, unsigned char *mac_addr) +{ + struct net_dev_context *nd; + struct net_device *dev; + + pr_info("Received netinfo from %s\n", iface->description); + + nd = get_net_dev_context(iface); + if (!nd) + return; + + dev = nd->dev; + if (!dev) + return; + + if (mac_addr) + memcpy(dev->dev_addr, mac_addr, ETH_ALEN); + + if (nd->link_stat != link_stat) { + nd->link_stat = link_stat; + if (nd->link_stat) + netif_wake_queue(dev); + else + netif_stop_queue(dev); + } +} +EXPORT_SYMBOL(most_deliver_netinfo); + +module_init(most_net_init); +module_exit(most_net_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>"); +MODULE_DESCRIPTION("Networking Application Interface Module for MostCore"); diff --git a/drivers/staging/most/aim-network/networking.h b/drivers/staging/most/aim-network/networking.h new file mode 100644 index 000000000000..1b8b434fabb0 --- /dev/null +++ b/drivers/staging/most/aim-network/networking.h @@ -0,0 +1,23 @@ +/* + * Networking AIM - Networking Application Interface Module for MostCore + * + * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This file is licensed under GPLv2. + */ +#ifndef _NETWORKING_H_ +#define _NETWORKING_H_ + +#include "mostcore.h" + + +void most_deliver_netinfo(struct most_interface *iface, + unsigned char link_stat, unsigned char *mac_addr); + + +#endif diff --git a/drivers/staging/most/aim-sound/Kconfig b/drivers/staging/most/aim-sound/Kconfig new file mode 100644 index 000000000000..3194c219ff14 --- /dev/null +++ b/drivers/staging/most/aim-sound/Kconfig @@ -0,0 +1,13 @@ +# +# MOST ALSA configuration +# + +config AIM_SOUND + tristate "ALSA AIM" + depends on SND + select SND_PCM + ---help--- + Say Y here if you want to commumicate via ALSA/sound devices. + + To compile this driver as a module, choose M here: the + module will be called aim_sound. diff --git a/drivers/staging/most/aim-sound/Makefile b/drivers/staging/most/aim-sound/Makefile new file mode 100644 index 000000000000..beba9586fd28 --- /dev/null +++ b/drivers/staging/most/aim-sound/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_AIM_SOUND) += aim_sound.o + +aim_sound-objs := sound.o +ccflags-y += -Idrivers/staging/most/mostcore/ diff --git a/drivers/staging/most/aim-sound/sound.c b/drivers/staging/most/aim-sound/sound.c new file mode 100644 index 000000000000..860302eebda7 --- /dev/null +++ b/drivers/staging/most/aim-sound/sound.c @@ -0,0 +1,758 @@ +/* + * sound.c - Audio Application Interface Module for Mostcore + * + * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This file is licensed under GPLv2. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/module.h> +#include <linux/printk.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <linux/sched.h> +#include <linux/kthread.h> +#include <mostcore.h> + +#define DRIVER_NAME "sound" + +static struct list_head dev_list; + +/** + * struct channel - private structure to keep channel specific data + * @substream: stores the substream structure + * @iface: interface for which the channel belongs to + * @cfg: channel configuration + * @card: registered sound card + * @list: list for private use + * @id: channel index + * @period_pos: current period position (ring buffer) + * @buffer_pos: current buffer position (ring buffer) + * @is_stream_running: identifies whether a stream is running or not + * @opened: set when the stream is opened + * @playback_task: playback thread + * @playback_waitq: waitq used by playback thread + */ +struct channel { + struct snd_pcm_substream *substream; + struct most_interface *iface; + struct most_channel_config *cfg; + struct snd_card *card; + struct list_head list; + int id; + unsigned int period_pos; + unsigned int buffer_pos; + bool is_stream_running; + + struct task_struct *playback_task; + wait_queue_head_t playback_waitq; + + void (*copy_fn)(void *alsa, void *most, unsigned int bytes); +}; + +#define MOST_PCM_INFO (SNDRV_PCM_INFO_MMAP | \ + SNDRV_PCM_INFO_MMAP_VALID | \ + SNDRV_PCM_INFO_BATCH | \ + SNDRV_PCM_INFO_INTERLEAVED | \ + SNDRV_PCM_INFO_BLOCK_TRANSFER) + +/** + * Initialization of struct snd_pcm_hardware + */ +static struct snd_pcm_hardware pcm_hardware_template = { + .info = MOST_PCM_INFO, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 8, +}; + +#define swap16(val) ( \ + (((u16)(val) << 8) & (u16)0xFF00) | \ + (((u16)(val) >> 8) & (u16)0x00FF)) + +#define swap32(val) ( \ + (((u32)(val) << 24) & (u32)0xFF000000) | \ + (((u32)(val) << 8) & (u32)0x00FF0000) | \ + (((u32)(val) >> 8) & (u32)0x0000FF00) | \ + (((u32)(val) >> 24) & (u32)0x000000FF)) + +static void swap_copy16(u16 *dest, const u16 *source, unsigned int bytes) +{ + unsigned int i = 0; + + while (i < (bytes / 2)) { + dest[i] = swap16(source[i]); + i++; + } +} + +static void swap_copy24(u8 *dest, const u8 *source, unsigned int bytes) +{ + unsigned int i = 0; + + while (i < bytes - 2) { + dest[i] = source[i + 2]; + dest[i + 1] = source[i + 1]; + dest[i + 2] = source[i]; + i += 3; + } +} + +static void swap_copy32(u32 *dest, const u32 *source, unsigned int bytes) +{ + unsigned int i = 0; + + while (i < bytes / 4) { + dest[i] = swap32(source[i]); + i++; + } +} + +static void alsa_to_most_memcpy(void *alsa, void *most, unsigned int bytes) +{ + memcpy(most, alsa, bytes); +} + +static void alsa_to_most_copy16(void *alsa, void *most, unsigned int bytes) +{ + swap_copy16(most, alsa, bytes); +} + +static void alsa_to_most_copy24(void *alsa, void *most, unsigned int bytes) +{ + swap_copy24(most, alsa, bytes); +} + +static void alsa_to_most_copy32(void *alsa, void *most, unsigned int bytes) +{ + swap_copy32(most, alsa, bytes); +} + +static void most_to_alsa_memcpy(void *alsa, void *most, unsigned int bytes) +{ + memcpy(alsa, most, bytes); +} + +static void most_to_alsa_copy16(void *alsa, void *most, unsigned int bytes) +{ + swap_copy16(alsa, most, bytes); +} + +static void most_to_alsa_copy24(void *alsa, void *most, unsigned int bytes) +{ + swap_copy24(alsa, most, bytes); +} + +static void most_to_alsa_copy32(void *alsa, void *most, unsigned int bytes) +{ + swap_copy32(alsa, most, bytes); +} + +/** + * get_channel - get pointer to channel + * @iface: interface structure + * @channel_id: channel ID + * + * This traverses the channel list and returns the channel matching the + * ID and interface. + * + * Returns pointer to channel on success or NULL otherwise. + */ +static struct channel *get_channel(struct most_interface *iface, + int channel_id) +{ + struct channel *channel, *tmp; + + list_for_each_entry_safe(channel, tmp, &dev_list, list) { + if ((channel->iface == iface) && (channel->id == channel_id)) + return channel; + } + + return NULL; +} + +/** + * copy_data - implements data copying function + * @channel: channel + * @mbo: MBO from core + * + * Copy data from/to ring buffer to/from MBO and update the buffer position + */ +static bool copy_data(struct channel *channel, struct mbo *mbo) +{ + struct snd_pcm_runtime *const runtime = channel->substream->runtime; + unsigned int const frame_bytes = channel->cfg->subbuffer_size; + unsigned int const buffer_size = runtime->buffer_size; + unsigned int frames; + unsigned int fr0; + + if (channel->cfg->direction & MOST_CH_RX) + frames = mbo->processed_length / frame_bytes; + else + frames = mbo->buffer_length / frame_bytes; + fr0 = min(buffer_size - channel->buffer_pos, frames); + + channel->copy_fn(runtime->dma_area + channel->buffer_pos * frame_bytes, + mbo->virt_address, + fr0 * frame_bytes); + + if (frames > fr0) { + /* wrap around at end of ring buffer */ + channel->copy_fn(runtime->dma_area, + mbo->virt_address + fr0 * frame_bytes, + (frames - fr0) * frame_bytes); + } + + channel->buffer_pos += frames; + if (channel->buffer_pos >= buffer_size) + channel->buffer_pos -= buffer_size; + channel->period_pos += frames; + if (channel->period_pos >= runtime->period_size) { + channel->period_pos -= runtime->period_size; + return true; + } + + return false; +} + +/** + * playback_thread - function implements the playback thread + * @data: private data + * + * Thread which does the playback functionality in a loop. It waits for a free + * MBO from mostcore for a particular channel and copy the data from ring buffer + * to MBO. Submit the MBO back to mostcore, after copying the data. + * + * Returns 0 on success or error code otherwise. + */ +static int playback_thread(void *data) +{ + struct channel *const channel = data; + + pr_info("playback thread started\n"); + + while (!kthread_should_stop()) { + struct mbo *mbo = NULL; + bool period_elapsed = false; + int ret; + + wait_event_interruptible( + channel->playback_waitq, + kthread_should_stop() || + (mbo = most_get_mbo(channel->iface, channel->id))); + + if (!mbo) + continue; + + if (channel->is_stream_running) + period_elapsed = copy_data(channel, mbo); + else + memset(mbo->virt_address, 0, mbo->buffer_length); + + ret = most_submit_mbo(mbo); + if (ret) + channel->is_stream_running = false; + + if (period_elapsed) + snd_pcm_period_elapsed(channel->substream); + } + + return 0; +} + +/** + * pcm_open - implements open callback function for PCM middle layer + * @substream: pointer to ALSA PCM substream + * + * This is called when a PCM substream is opened. At least, the function should + * initialize the runtime->hw record. + * + * Returns 0 on success or error code otherwise. + */ +static int pcm_open(struct snd_pcm_substream *substream) +{ + struct channel *channel = substream->private_data; + struct snd_pcm_runtime *runtime = substream->runtime; + struct most_channel_config *cfg = channel->cfg; + + pr_info("pcm_open(), %s\n", substream->name); + + channel->substream = substream; + + if (cfg->direction == MOST_CH_TX) { + init_waitqueue_head(&channel->playback_waitq); + channel->playback_task = kthread_run(&playback_thread, channel, + "most_audio_playback"); + if (IS_ERR(channel->playback_task)) + return PTR_ERR(channel->playback_task); + } + + if (most_start_channel(channel->iface, channel->id)) { + pr_err("most_start_channel() failed!\n"); + if (cfg->direction == MOST_CH_TX) + kthread_stop(channel->playback_task); + return -EBUSY; + } + + runtime->hw = pcm_hardware_template; + runtime->hw.buffer_bytes_max = cfg->num_buffers * cfg->buffer_size; + runtime->hw.period_bytes_min = cfg->buffer_size; + runtime->hw.period_bytes_max = cfg->buffer_size; + runtime->hw.periods_min = 1; + runtime->hw.periods_max = cfg->num_buffers; + + return 0; +} + +/** + * pcm_close - implements close callback function for PCM middle layer + * @substream: sub-stream pointer + * + * Obviously, this is called when a PCM substream is closed. Any private + * instance for a PCM substream allocated in the open callback will be + * released here. + * + * Returns 0 on success or error code otherwise. + */ +static int pcm_close(struct snd_pcm_substream *substream) +{ + struct channel *channel = substream->private_data; + + pr_info("pcm_close(), %s\n", substream->name); + + if (channel->cfg->direction == MOST_CH_TX) + kthread_stop(channel->playback_task); + most_stop_channel(channel->iface, channel->id); + + return 0; +} + +/** + * pcm_hw_params - implements hw_params callback function for PCM middle layer + * @substream: sub-stream pointer + * @hw_params: contains the hardware parameters set by the application + * + * This is called when the hardware parameters is set by the application, that + * is, once when the buffer size, the period size, the format, etc. are defined + * for the PCM substream. Many hardware setups should be done is this callback, + * including the allocation of buffers. + * + * Returns 0 on success or error code otherwise. + */ +static int pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + pr_info("pcm_hw_params()\n"); + + return snd_pcm_lib_alloc_vmalloc_buffer(substream, + params_buffer_bytes(hw_params)); +} + +/** + * pcm_hw_free - implements hw_free callback function for PCM middle layer + * @substream: substream pointer + * + * This is called to release the resources allocated via hw_params. + * This function will be always called before the close callback is called. + * + * Returns 0 on success or error code otherwise. + */ +static int pcm_hw_free(struct snd_pcm_substream *substream) +{ + pr_info("pcm_hw_free()\n"); + + return snd_pcm_lib_free_vmalloc_buffer(substream); +} + +/** + * pcm_prepare - implements prepare callback function for PCM middle layer + * @substream: substream pointer + * + * This callback is called when the PCM is "prepared". Format rate, sample rate, + * etc., can be set here. This callback can be called many times at each setup. + * + * Returns 0 on success or error code otherwise. + */ +static int pcm_prepare(struct snd_pcm_substream *substream) +{ + struct channel *channel = substream->private_data; + struct snd_pcm_runtime *runtime = substream->runtime; + struct most_channel_config *cfg = channel->cfg; + int width = snd_pcm_format_physical_width(runtime->format); + + channel->copy_fn = NULL; + + if (cfg->direction == MOST_CH_TX) { + if (snd_pcm_format_big_endian(runtime->format) || width == 8) + channel->copy_fn = alsa_to_most_memcpy; + else if (width == 16) + channel->copy_fn = alsa_to_most_copy16; + else if (width == 24) + channel->copy_fn = alsa_to_most_copy24; + else if (width == 32) + channel->copy_fn = alsa_to_most_copy32; + } else { + if (snd_pcm_format_big_endian(runtime->format) || width == 8) + channel->copy_fn = most_to_alsa_memcpy; + else if (width == 16) + channel->copy_fn = most_to_alsa_copy16; + else if (width == 24) + channel->copy_fn = most_to_alsa_copy24; + else if (width == 32) + channel->copy_fn = most_to_alsa_copy32; + } + + if (!channel->copy_fn) { + pr_err("unsupported format\n"); + return -EINVAL; + } + + channel->period_pos = 0; + channel->buffer_pos = 0; + + return 0; +} + +/** + * pcm_trigger - implements trigger callback function for PCM middle layer + * @substream: substream pointer + * @cmd: action to perform + * + * This is called when the PCM is started, stopped or paused. The action will be + * specified in the second argument, SNDRV_PCM_TRIGGER_XXX + * + * Returns 0 on success or error code otherwise. + */ +static int pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct channel *channel = substream->private_data; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + channel->is_stream_running = true; + return 0; + + case SNDRV_PCM_TRIGGER_STOP: + channel->is_stream_running = false; + return 0; + + default: + pr_info("pcm_trigger(), invalid\n"); + return -EINVAL; + } + return 0; +} + +/** + * pcm_pointer - implements pointer callback function for PCM middle layer + * @substream: substream pointer + * + * This callback is called when the PCM middle layer inquires the current + * hardware position on the buffer. The position must be returned in frames, + * ranging from 0 to buffer_size-1. + */ +static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream) +{ + struct channel *channel = substream->private_data; + + return channel->buffer_pos; +} + +/** + * Initialization of struct snd_pcm_ops + */ +static struct snd_pcm_ops pcm_ops = { + .open = pcm_open, + .close = pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = pcm_hw_params, + .hw_free = pcm_hw_free, + .prepare = pcm_prepare, + .trigger = pcm_trigger, + .pointer = pcm_pointer, + .page = snd_pcm_lib_get_vmalloc_page, + .mmap = snd_pcm_lib_mmap_vmalloc, +}; + + +int split_arg_list(char *buf, char **card_name, char **pcm_format) +{ + *card_name = strsep(&buf, "."); + if (!*card_name) + return -EIO; + *pcm_format = strsep(&buf, ".\n"); + if (!*pcm_format) + return -EIO; + return 0; +} + +int audio_set_pcm_format(char *pcm_format, struct most_channel_config *cfg) +{ + if (!strcmp(pcm_format, "1x8")) { + if (cfg->subbuffer_size != 1) + goto error; + pr_info("PCM format is 8-bit mono\n"); + pcm_hardware_template.formats = SNDRV_PCM_FMTBIT_S8; + } else if (!strcmp(pcm_format, "2x16")) { + if (cfg->subbuffer_size != 4) + goto error; + pr_info("PCM format is 16-bit stereo\n"); + pcm_hardware_template.formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S16_BE; + } else if (!strcmp(pcm_format, "2x24")) { + if (cfg->subbuffer_size != 6) + goto error; + pr_info("PCM format is 24-bit stereo\n"); + pcm_hardware_template.formats = SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S24_3BE; + } else if (!strcmp(pcm_format, "2x32")) { + if (cfg->subbuffer_size != 8) + goto error; + pr_info("PCM format is 32-bit stereo\n"); + pcm_hardware_template.formats = SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S32_BE; + } else { + pr_err("PCM format %s not supported\n", pcm_format); + return -EIO; + } + return 0; +error: + pr_err("Audio resolution doesn't fit subbuffer size\n"); + return -EINVAL; +} + +/** + * audio_probe_channel - probe function of the driver module + * @iface: pointer to interface instance + * @channel_id: channel index/ID + * @cfg: pointer to actual channel configuration + * @parent: pointer to kobject (needed for sysfs hook-up) + * @arg_list: string that provides the name of the device to be created in /dev + * plus the desired audio resolution + * + * Creates sound card, pcm device, sets pcm ops and registers sound card. + * + * Returns 0 on success or error code otherwise. + */ +static int audio_probe_channel(struct most_interface *iface, int channel_id, + struct most_channel_config *cfg, + struct kobject *parent, char *arg_list) +{ + struct channel *channel; + struct snd_card *card; + struct snd_pcm *pcm; + int playback_count = 0; + int capture_count = 0; + int ret; + int direction; + char *card_name; + char *pcm_format; + + pr_info("sound_probe_channel()\n"); + + if (!iface) + return -EINVAL; + + if (cfg->data_type != MOST_CH_SYNC) { + pr_err("Incompatible channel type\n"); + return -EINVAL; + } + + if (get_channel(iface, channel_id)) { + pr_err("channel (%s:%d) is already linked\n", + iface->description, channel_id); + return -EINVAL; + } + + if (cfg->direction == MOST_CH_TX) { + playback_count = 1; + direction = SNDRV_PCM_STREAM_PLAYBACK; + } else { + capture_count = 1; + direction = SNDRV_PCM_STREAM_CAPTURE; + } + + ret = split_arg_list(arg_list, &card_name, &pcm_format); + if (ret < 0) { + pr_info("PCM format missing\n"); + return ret; + } + if (audio_set_pcm_format(pcm_format, cfg)) + return ret; + + ret = snd_card_new(NULL, -1, card_name, THIS_MODULE, + sizeof(*channel), &card); + if (ret < 0) + return ret; + + channel = card->private_data; + channel->card = card; + channel->cfg = cfg; + channel->iface = iface; + channel->id = channel_id; + + snprintf(card->driver, sizeof(card->driver), "%s", DRIVER_NAME); + snprintf(card->shortname, sizeof(card->shortname), "MOST:%d", + card->number); + snprintf(card->longname, sizeof(card->longname), "%s at %s, ch %d", + card->shortname, iface->description, channel_id); + + ret = snd_pcm_new(card, card_name, 0, playback_count, + capture_count, &pcm); + if (ret < 0) + goto err_free_card; + + pcm->private_data = channel; + + snd_pcm_set_ops(pcm, direction, &pcm_ops); + + ret = snd_card_register(card); + if (ret < 0) + goto err_free_card; + + list_add_tail(&channel->list, &dev_list); + + return 0; + +err_free_card: + snd_card_free(card); + return ret; +} + +/** + * audio_disconnect_channel - function to disconnect a channel + * @iface: pointer to interface instance + * @channel_id: channel index + * + * This frees allocated memory and removes the sound card from ALSA + * + * Returns 0 on success or error code otherwise. + */ +static int audio_disconnect_channel(struct most_interface *iface, + int channel_id) +{ + struct channel *channel; + + pr_info("sound_disconnect_channel()\n"); + + channel = get_channel(iface, channel_id); + if (!channel) { + pr_err("sound_disconnect_channel(), invalid channel %d\n", + channel_id); + return -EINVAL; + } + + list_del(&channel->list); + snd_card_free(channel->card); + + return 0; +} + +/** + * audio_rx_completion - completion handler for rx channels + * @mbo: pointer to buffer object that has completed + * + * This searches for the channel this MBO belongs to and copy the data from MBO + * to ring buffer + * + * Returns 0 on success or error code otherwise. + */ +static int audio_rx_completion(struct mbo *mbo) +{ + struct channel *channel = get_channel(mbo->ifp, mbo->hdm_channel_id); + bool period_elapsed = false; + + if (!channel) { + pr_err("sound_rx_completion(), invalid channel %d\n", + mbo->hdm_channel_id); + return -EINVAL; + } + + if (channel->is_stream_running) + period_elapsed = copy_data(channel, mbo); + + most_put_mbo(mbo); + + if (period_elapsed) + snd_pcm_period_elapsed(channel->substream); + + return 0; +} + +/** + * audio_tx_completion - completion handler for tx channels + * @iface: pointer to interface instance + * @channel_id: channel index/ID + * + * This searches the channel that belongs to this combination of interface + * pointer and channel ID and wakes a process sitting in the wait queue of + * this channel. + * + * Returns 0 on success or error code otherwise. + */ +static int audio_tx_completion(struct most_interface *iface, int channel_id) +{ + struct channel *channel = get_channel(iface, channel_id); + + if (!channel) { + pr_err("sound_tx_completion(), invalid channel %d\n", + channel_id); + return -EINVAL; + } + + wake_up_interruptible(&channel->playback_waitq); + + return 0; +} + +/** + * Initialization of the struct most_aim + */ +static struct most_aim audio_aim = { + .name = DRIVER_NAME, + .probe_channel = audio_probe_channel, + .disconnect_channel = audio_disconnect_channel, + .rx_completion = audio_rx_completion, + .tx_completion = audio_tx_completion, +}; + +static int __init audio_init(void) +{ + pr_info("init()\n"); + + INIT_LIST_HEAD(&dev_list); + + return most_register_aim(&audio_aim); +} + +static void __exit audio_exit(void) +{ + struct channel *channel, *tmp; + + pr_info("exit()\n"); + + list_for_each_entry_safe(channel, tmp, &dev_list, list) { + list_del(&channel->list); + snd_card_free(channel->card); + } + + most_deregister_aim(&audio_aim); +} + +module_init(audio_init); +module_exit(audio_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>"); +MODULE_DESCRIPTION("Audio Application Interface Module for MostCore"); diff --git a/drivers/staging/most/aim-v4l2/Kconfig b/drivers/staging/most/aim-v4l2/Kconfig new file mode 100644 index 000000000000..d70eaaf0936c --- /dev/null +++ b/drivers/staging/most/aim-v4l2/Kconfig @@ -0,0 +1,12 @@ +# +# MOST V4L2 configuration +# + +config AIM_V4L2 + tristate "V4L2 AIM" + depends on VIDEO_V4L2 + ---help--- + Say Y here if you want to commumicate via Video 4 Linux. + + To compile this driver as a module, choose M here: the + module will be called aim_v4l2.
\ No newline at end of file diff --git a/drivers/staging/most/aim-v4l2/Makefile b/drivers/staging/most/aim-v4l2/Makefile new file mode 100644 index 000000000000..28aa948d6609 --- /dev/null +++ b/drivers/staging/most/aim-v4l2/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_AIM_V4L2) += aim_v4l2.o + +aim_v4l2-objs := video.o + +ccflags-y += -Idrivers/staging/most/mostcore/ +ccflags-y += -Idrivers/media/video diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c new file mode 100644 index 000000000000..d9687910e4a4 --- /dev/null +++ b/drivers/staging/most/aim-v4l2/video.c @@ -0,0 +1,635 @@ +/* + * V4L2 AIM - V4L2 Application Interface Module for MostCore + * + * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This file is licensed under GPLv2. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/device.h> +#include <linux/suspend.h> +#include <linux/videodev2.h> +#include <linux/mutex.h> +#include <media/v4l2-common.h> +#include <media/v4l2-ioctl.h> +#include <media/v4l2-event.h> +#include <media/v4l2-device.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-fh.h> + +#include "mostcore.h" + + +#define V4L2_AIM_MAX_INPUT 1 + + +struct most_video_dev { + struct most_interface *iface; + int ch_idx; + struct list_head list; + bool mute; + + struct list_head pending_mbos; + spinlock_t list_lock; + + struct v4l2_device v4l2_dev; + atomic_t access_ref; + struct video_device *vdev; + unsigned int ctrl_input; + + struct mutex lock; + + wait_queue_head_t wait_data; +}; + +struct aim_fh { + /* must be the first field of this struct! */ + struct v4l2_fh fh; + struct most_video_dev *mdev; + u32 offs; +}; + + +static struct list_head video_devices = LIST_HEAD_INIT(video_devices); +static struct spinlock list_lock; +static struct most_aim aim_info; + + +static inline bool data_ready(struct most_video_dev *mdev) +{ + return !list_empty(&mdev->pending_mbos); +} + +static inline struct mbo *get_top_mbo(struct most_video_dev *mdev) +{ + return list_first_entry(&mdev->pending_mbos, struct mbo, list); +} + + +static int aim_vdev_open(struct file *filp) +{ + int ret; + struct video_device *vdev = video_devdata(filp); + struct most_video_dev *mdev = video_drvdata(filp); + struct aim_fh *fh; + + pr_info("aim_vdev_open()\n"); + + switch (vdev->vfl_type) { + case VFL_TYPE_GRABBER: + break; + default: + return -EINVAL; + } + + fh = kzalloc(sizeof(struct aim_fh), GFP_KERNEL); + if (!fh) + return -ENOMEM; + + if (!atomic_inc_and_test(&mdev->access_ref)) { + pr_err("too many clients\n"); + ret = -EBUSY; + goto err_dec; + } + + fh->mdev = mdev; + v4l2_fh_init(&fh->fh, vdev); + filp->private_data = fh; + + v4l2_fh_add(&fh->fh); + + ret = most_start_channel(mdev->iface, mdev->ch_idx); + if (ret) { + pr_err("most_start_channel() failed\n"); + goto err_rm; + } + + return 0; + +err_rm: + v4l2_fh_del(&fh->fh); + v4l2_fh_exit(&fh->fh); + +err_dec: + atomic_dec(&mdev->access_ref); + kfree(fh); + return ret; +} + +static int aim_vdev_close(struct file *filp) +{ + struct aim_fh *fh = filp->private_data; + struct most_video_dev *mdev = fh->mdev; + struct mbo *mbo, *tmp; + + pr_info("aim_vdev_close()\n"); + + /* + * We need to put MBOs back before we call most_stop_channel() + * to deallocate MBOs. + * From the other hand mostcore still calling rx_completion() + * to deliver MBOs until most_stop_channel() is called. + * Use mute to work around this issue. + * This must be implemented in core. + */ + + spin_lock(&mdev->list_lock); + mdev->mute = true; + list_for_each_entry_safe(mbo, tmp, &mdev->pending_mbos, list) { + list_del(&mbo->list); + spin_unlock(&mdev->list_lock); + most_put_mbo(mbo); + spin_lock(&mdev->list_lock); + } + spin_unlock(&mdev->list_lock); + most_stop_channel(mdev->iface, mdev->ch_idx); + mdev->mute = false; + + v4l2_fh_del(&fh->fh); + v4l2_fh_exit(&fh->fh); + + atomic_dec(&mdev->access_ref); + kfree(fh); + return 0; +} + +static ssize_t aim_vdev_read(struct file *filp, char __user *buf, + size_t count, loff_t *pos) +{ + struct aim_fh *fh = filp->private_data; + struct most_video_dev *mdev = fh->mdev; + int ret = 0; + + if (*pos) + return -ESPIPE; + + if (!mdev) + return -ENODEV; + + /* wait for the first buffer */ + if (!(filp->f_flags & O_NONBLOCK)) { + if (wait_event_interruptible(mdev->wait_data, data_ready(mdev))) + return -ERESTARTSYS; + } + + if (!data_ready(mdev)) + return -EAGAIN; + + while (count > 0 && data_ready(mdev)) { + struct mbo *const mbo = get_top_mbo(mdev); + int const rem = mbo->processed_length - fh->offs; + int const cnt = rem < count ? rem : count; + + if (copy_to_user(buf, mbo->virt_address + fh->offs, cnt)) { + pr_err("read: copy_to_user failed\n"); + if (!ret) + ret = -EFAULT; + return ret; + } + + fh->offs += cnt; + count -= cnt; + buf += cnt; + ret += cnt; + + if (cnt >= rem) { + fh->offs = 0; + spin_lock(&mdev->list_lock); + list_del(&mbo->list); + spin_unlock(&mdev->list_lock); + most_put_mbo(mbo); + } + } + return ret; +} + +static unsigned int aim_vdev_poll(struct file *filp, poll_table *wait) +{ + struct aim_fh *fh = filp->private_data; + struct most_video_dev *mdev = fh->mdev; + unsigned int mask = 0; + + /* only wait if no data is available */ + if (!data_ready(mdev)) + poll_wait(filp, &mdev->wait_data, wait); + if (data_ready(mdev)) + mask |= POLLIN | POLLRDNORM; + + return mask; +} + +static void aim_set_format_struct(struct v4l2_format *f) +{ + f->fmt.pix.width = 8; + f->fmt.pix.height = 8; + f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; + f->fmt.pix.bytesperline = 0; + f->fmt.pix.sizeimage = 188 * 2; + f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; + f->fmt.pix.field = V4L2_FIELD_NONE; + f->fmt.pix.priv = 0; +} + +static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd, + struct v4l2_format *format) +{ +#if 0 + u32 const pixfmt = format->fmt.pix.pixelformat; + const char *fmt; + + if (pixfmt != V4L2_PIX_FMT_MPEG) { + if (cmd == VIDIOC_TRY_FMT) + fmt = KERN_ERR "try %c%c%c%c failed\n"; + else + fmt = KERN_ERR "set %c%c%c%c failed\n"; + } else { + if (cmd == VIDIOC_TRY_FMT) + fmt = KERN_ERR "try %c%c%c%c\n"; + else + fmt = KERN_ERR "set %c%c%c%c\n"; + } + printk(fmt, + (pixfmt) & 255, + (pixfmt >> 8) & 255, + (pixfmt >> 16) & 255, + (pixfmt >> 24) & 255); +#endif + + if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG) + return -EINVAL; + + if (cmd == VIDIOC_TRY_FMT) + return 0; + + aim_set_format_struct(format); + + return 0; +} + + +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct aim_fh *fh = priv; + struct most_video_dev *mdev = fh->mdev; + + pr_info("vidioc_querycap()\n"); + + strlcpy(cap->driver, "v4l2_most_aim", sizeof(cap->driver)); + strlcpy(cap->card, "my_card", sizeof(cap->card)); + snprintf(cap->bus_info, sizeof(cap->bus_info), + "%s", mdev->iface->description); + + cap->capabilities = + V4L2_CAP_READWRITE | + V4L2_CAP_TUNER | + V4L2_CAP_VIDEO_CAPTURE; + return 0; +} + +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + pr_info("vidioc_enum_fmt_vid_cap() %d\n", f->index); + + if (f->index) + return -EINVAL; + + strcpy(f->description, "MPEG"); + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + f->flags = V4L2_FMT_FLAG_COMPRESSED; + f->pixelformat = V4L2_PIX_FMT_MPEG; + + return 0; +} + +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + pr_info("vidioc_g_fmt_vid_cap()\n"); + + aim_set_format_struct(f); + return 0; +} + +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct aim_fh *fh = priv; + struct most_video_dev *mdev = fh->mdev; + + return aim_set_format(mdev, VIDIOC_TRY_FMT, f); +} + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct aim_fh *fh = priv; + struct most_video_dev *mdev = fh->mdev; + + return aim_set_format(mdev, VIDIOC_S_FMT, f); +} + +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) +{ + pr_info("vidioc_g_std()\n"); + + *norm = V4L2_STD_UNKNOWN; + return 0; +} + +static int vidioc_enum_input(struct file *file, void *priv, + struct v4l2_input *input) +{ + struct aim_fh *fh = priv; + struct most_video_dev *mdev = fh->mdev; + + if (input->index >= V4L2_AIM_MAX_INPUT) + return -EINVAL; + + strcpy(input->name, "MOST Video"); + input->type |= V4L2_INPUT_TYPE_CAMERA; + input->audioset = 0; + + input->std = mdev->vdev->tvnorms; + + return 0; +} + +static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) +{ + struct aim_fh *fh = priv; + struct most_video_dev *mdev = fh->mdev; + *i = mdev->ctrl_input; + return 0; +} + +static int vidioc_s_input(struct file *file, void *priv, unsigned int index) +{ + struct aim_fh *fh = priv; + struct most_video_dev *mdev = fh->mdev; + + pr_info("vidioc_s_input(%d)\n", index); + + if (index >= V4L2_AIM_MAX_INPUT) + return -EINVAL; + mdev->ctrl_input = index; + return 0; +} + +static struct v4l2_file_operations aim_fops = { + .owner = THIS_MODULE, + .open = aim_vdev_open, + .release = aim_vdev_close, + .read = aim_vdev_read, + .poll = aim_vdev_poll, + .unlocked_ioctl = video_ioctl2, +}; + +static const struct v4l2_ioctl_ops video_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_g_std = vidioc_g_std, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, +}; + +static const struct video_device aim_videodev_template = { + .fops = &aim_fops, + .release = video_device_release, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = V4L2_STD_UNKNOWN, +}; + +/**************************************************************************/ + +static struct most_video_dev *get_aim_dev( + struct most_interface *iface, int channel_idx) +{ + struct most_video_dev *mdev, *tmp; + + spin_lock(&list_lock); + list_for_each_entry_safe(mdev, tmp, &video_devices, list) { + if (mdev->iface == iface && mdev->ch_idx == channel_idx) { + spin_unlock(&list_lock); + return mdev; + } + } + spin_unlock(&list_lock); + return 0; +} + +static int aim_rx_data(struct mbo *mbo) +{ + struct most_video_dev *mdev = + get_aim_dev(mbo->ifp, mbo->hdm_channel_id); + + if (!mdev) + return -EIO; + + spin_lock(&mdev->list_lock); + if (unlikely(mdev->mute)) { + spin_unlock(&mdev->list_lock); + return -EIO; + } + + list_add_tail(&mbo->list, &mdev->pending_mbos); + spin_unlock(&mdev->list_lock); + wake_up_interruptible(&mdev->wait_data); + return 0; +} + +static int aim_register_videodev(struct most_video_dev *mdev) +{ + int retval = -ENOMEM; + int ret; + + pr_info("aim_register_videodev()\n"); + + init_waitqueue_head(&mdev->wait_data); + + /* allocate and fill v4l2 video struct */ + mdev->vdev = video_device_alloc(); + if (!mdev->vdev) + return -ENOMEM; + + /* Fill the video capture device struct */ + *mdev->vdev = aim_videodev_template; + mdev->vdev->v4l2_dev = &mdev->v4l2_dev; + mdev->vdev->lock = &mdev->lock; + strcpy(mdev->vdev->name, "most v4l2 aim video"); + + /* Register the v4l2 device */ + video_set_drvdata(mdev->vdev, mdev); + retval = video_register_device(mdev->vdev, VFL_TYPE_GRABBER, -1); + if (retval != 0) { + pr_err("video_register_device failed (%d)\n", retval); + ret = -ENODEV; + goto err_vbi_dev; + } + + return 0; + +err_vbi_dev: + video_device_release(mdev->vdev); + return ret; +} + +static void aim_unregister_videodev(struct most_video_dev *mdev) +{ + pr_info("aim_unregister_videodev()\n"); + + video_unregister_device(mdev->vdev); +} + + +static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev) +{ + struct most_video_dev *mdev = + container_of(v4l2_dev, struct most_video_dev, v4l2_dev); + + v4l2_device_unregister(v4l2_dev); + kfree(mdev); +} + +static int aim_probe_channel(struct most_interface *iface, int channel_idx, + struct most_channel_config *ccfg, + struct kobject *parent, char *name) +{ + int ret; + struct most_video_dev *mdev = get_aim_dev(iface, channel_idx); + + pr_info("aim_probe_channel()\n"); + + if (mdev) { + pr_err("channel already linked\n"); + return -EEXIST; + } + + if (ccfg->direction != MOST_CH_RX) { + pr_err("wrong direction, expect rx\n"); + return -EINVAL; + } + + if (ccfg->data_type != MOST_CH_SYNC && + ccfg->data_type != MOST_CH_ISOC_AVP) { + pr_err("wrong channel type, expect sync or isoc_avp\n"); + return -EINVAL; + } + + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + if (!mdev) + return -ENOMEM; + + mutex_init(&mdev->lock); + atomic_set(&mdev->access_ref, -1); + spin_lock_init(&mdev->list_lock); + INIT_LIST_HEAD(&mdev->pending_mbos); + mdev->iface = iface; + mdev->ch_idx = channel_idx; + mdev->v4l2_dev.release = aim_v4l2_dev_release; + + /* Create the v4l2_device */ + strlcpy(mdev->v4l2_dev.name, "most_video_device", + sizeof(mdev->v4l2_dev.name)); + ret = v4l2_device_register(NULL, &mdev->v4l2_dev); + if (ret) { + pr_err("v4l2_device_register() failed\n"); + kfree(mdev); + return ret; + } + + ret = aim_register_videodev(mdev); + if (ret) + goto err_unreg; + + spin_lock(&list_lock); + list_add(&mdev->list, &video_devices); + spin_unlock(&list_lock); + return 0; + +err_unreg: + v4l2_device_disconnect(&mdev->v4l2_dev); + v4l2_device_put(&mdev->v4l2_dev); + return ret; +} + +static int aim_disconnect_channel(struct most_interface *iface, + int channel_idx) +{ + struct most_video_dev *mdev = get_aim_dev(iface, channel_idx); + + pr_info("aim_disconnect_channel()\n"); + + if (!mdev) { + pr_err("no such channel is linked\n"); + return -ENOENT; + } + + spin_lock(&list_lock); + list_del(&mdev->list); + spin_unlock(&list_lock); + + aim_unregister_videodev(mdev); + v4l2_device_disconnect(&mdev->v4l2_dev); + v4l2_device_put(&mdev->v4l2_dev); + return 0; +} + +static int __init aim_init(void) +{ + spin_lock_init(&list_lock); + + aim_info.name = "v4l"; + aim_info.probe_channel = aim_probe_channel; + aim_info.disconnect_channel = aim_disconnect_channel; + aim_info.rx_completion = aim_rx_data; + return most_register_aim(&aim_info); +} + +static void __exit aim_exit(void) +{ + struct most_video_dev *mdev, *tmp; + + /* + * As the mostcore currently doesn't call disconnect_channel() + * for linked channels while we call most_deregister_aim() + * we simulate this call here. + * This must be fixed in core. + */ + spin_lock(&list_lock); + list_for_each_entry_safe(mdev, tmp, &video_devices, list) { + list_del(&mdev->list); + spin_unlock(&list_lock); + + aim_unregister_videodev(mdev); + v4l2_device_disconnect(&mdev->v4l2_dev); + v4l2_device_put(&mdev->v4l2_dev); + spin_lock(&list_lock); + } + spin_unlock(&list_lock); + + most_deregister_aim(&aim_info); + BUG_ON(!list_empty(&video_devices)); +} + +module_init(aim_init); +module_exit(aim_exit); + +MODULE_DESCRIPTION("V4L2 Application Interface Module for MostCore"); +MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/most/hdm-dim2/Kconfig b/drivers/staging/most/hdm-dim2/Kconfig new file mode 100644 index 000000000000..1d4ad1d67758 --- /dev/null +++ b/drivers/staging/most/hdm-dim2/Kconfig @@ -0,0 +1,16 @@ +# +# MediaLB configuration +# + +config HDM_DIM2 + tristate "DIM2 HDM" + depends on AIM_NETWORK + + ---help--- + Say Y here if you want to connect via MediaLB to network transceiver. + This device driver is platform dependent and needs an addtional + platform driver to be installed. For more information contact + maintainer of this driver. + + To compile this driver as a module, choose M here: the + module will be called hdm_dim2. diff --git a/drivers/staging/most/hdm-dim2/Makefile b/drivers/staging/most/hdm-dim2/Makefile new file mode 100644 index 000000000000..6bbee879a8ea --- /dev/null +++ b/drivers/staging/most/hdm-dim2/Makefile @@ -0,0 +1,5 @@ +obj-$(CONFIG_HDM_DIM2) += hdm_dim2.o + +hdm_dim2-objs := dim2_hdm.o dim2_hal.o dim2_sysfs.o +ccflags-y += -Idrivers/staging/most/mostcore/ +ccflags-y += -Idrivers/staging/most/aim-network/ diff --git a/drivers/staging/most/hdm-dim2/dim2_errors.h b/drivers/staging/most/hdm-dim2/dim2_errors.h new file mode 100644 index 000000000000..314f7de2be73 --- /dev/null +++ b/drivers/staging/most/hdm-dim2/dim2_errors.h @@ -0,0 +1,67 @@ +/* + * dim2_errors.h - Definitions of errors for DIM2 HAL API + * (MediaLB, Device Interface Macro IP, OS62420) + * + * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This file is licensed under GPLv2. + */ + +#ifndef _MOST_DIM_ERRORS_H +#define _MOST_DIM_ERRORS_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * MOST DIM errors. + */ +enum dim_errors_t { + /** Not an error */ + DIM_NO_ERROR = 0, + + /** Bad base address for DIM2 IP */ + DIM_INIT_ERR_DIM_ADDR = 0x10, + + /**< Bad MediaLB clock */ + DIM_INIT_ERR_MLB_CLOCK, + + /** Bad channel address */ + DIM_INIT_ERR_CHANNEL_ADDRESS, + + /** Out of DBR memory */ + DIM_INIT_ERR_OUT_OF_MEMORY, + + /** DIM API is called while DIM is not initialized successfully */ + DIM_ERR_DRIVER_NOT_INITIALIZED = 0x20, + + /** + * Configuration does not respect hardware limitations + * for isochronous or synchronous channels + */ + DIM_ERR_BAD_CONFIG, + + /** + * Buffer size does not respect hardware limitations + * for isochronous or synchronous channels + */ + DIM_ERR_BAD_BUFFER_SIZE, + + DIM_ERR_UNDERFLOW, + + DIM_ERR_OVERFLOW, +}; + + +#ifdef __cplusplus +} +#endif + +#endif /* _MOST_DIM_ERRORS_H */ diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c new file mode 100644 index 000000000000..01b748944ee4 --- /dev/null +++ b/drivers/staging/most/hdm-dim2/dim2_hal.c @@ -0,0 +1,919 @@ +/* + * dim2_hal.c - DIM2 HAL implementation + * (MediaLB, Device Interface Macro IP, OS62420) + * + * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This file is licensed under GPLv2. + */ + +/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */ + +#include "dim2_hal.h" +#include "dim2_errors.h" +#include "dim2_reg.h" +#include <linux/stddef.h> + + +/* + * The number of frames per sub-buffer for synchronous channels. + * Allowed values: 1, 2, 4, 8, 16, 32, 64. + */ +#define FRAMES_PER_SUBBUFF 16 + +/* + * Size factor for synchronous DBR buffer. + * Minimal value is 4*FRAMES_PER_SUBBUFF. + */ +#define SYNC_DBR_FACTOR (4u * (u16)FRAMES_PER_SUBBUFF) + +/* + * Size factor for isochronous DBR buffer. + * Minimal value is 3. + */ +#define ISOC_DBR_FACTOR 3u + +/* + * Number of 32-bit units for DBR map. + * + * 1: block size is 512, max allocation is 16K + * 2: block size is 256, max allocation is 8K + * 4: block size is 128, max allocation is 4K + * 8: block size is 64, max allocation is 2K + * + * Min allocated space is block size. + * Max possible allocated space is 32 blocks. + */ +#define DBR_MAP_SIZE 2 + + +/* -------------------------------------------------------------------------- */ +/* not configurable area */ + +#define CDT 0x00 +#define ADT 0x40 +#define MLB_CAT 0x80 +#define AHB_CAT 0x88 + +#define DBR_SIZE (16*1024) /* specified by IP */ +#define DBR_BLOCK_SIZE (DBR_SIZE / 32 / DBR_MAP_SIZE) + + +/* -------------------------------------------------------------------------- */ +/* generic helper functions and macros */ + +#define MLBC0_FCNT_VAL_MACRO(n) MLBC0_FCNT_VAL_ ## n ## FPSB +#define MLBC0_FCNT_VAL(fpsb) MLBC0_FCNT_VAL_MACRO(fpsb) + +static inline u32 bit_mask(u8 position) +{ + return (u32)1 << position; +} + +static inline bool dim_on_error(u8 error_id, const char *error_message) +{ + DIMCB_OnError(error_id, error_message); + return false; +} + + +/* -------------------------------------------------------------------------- */ +/* types and local variables */ + +struct lld_global_vars_t { + bool dim_is_initialized; + bool mcm_is_initialized; + struct dim2_regs *dim2; /* DIM2 core base address */ + u32 dbr_map[DBR_MAP_SIZE]; +}; + +static struct lld_global_vars_t g = { false }; + + +/* -------------------------------------------------------------------------- */ + +static int dbr_get_mask_size(u16 size) +{ + int i; + + for (i = 0; i < 6; i++) + if (size <= (DBR_BLOCK_SIZE << i)) + return 1 << i; + return 0; +} + +/** + * Allocates DBR memory. + * @param size Allocating memory size. + * @return Offset in DBR memory by success or DBR_SIZE if out of memory. + */ +static int alloc_dbr(u16 size) +{ + int mask_size; + int i, block_idx = 0; + + if (size <= 0) + return DBR_SIZE; /* out of memory */ + + mask_size = dbr_get_mask_size(size); + if (mask_size == 0) + return DBR_SIZE; /* out of memory */ + + for (i = 0; i < DBR_MAP_SIZE; i++) { + u32 const blocks = (size + DBR_BLOCK_SIZE - 1) / DBR_BLOCK_SIZE; + u32 mask = ~((~(u32)0) << blocks); + + do { + if ((g.dbr_map[i] & mask) == 0) { + g.dbr_map[i] |= mask; + return block_idx * DBR_BLOCK_SIZE; + } + block_idx += mask_size; + /* do shift left with 2 steps for case mask_size == 32 */ + mask <<= mask_size - 1; + } while ((mask <<= 1) != 0); + } + + return DBR_SIZE; /* out of memory */ +} + +static void free_dbr(int offs, int size) +{ + int block_idx = offs / DBR_BLOCK_SIZE; + u32 const blocks = (size + DBR_BLOCK_SIZE - 1) / DBR_BLOCK_SIZE; + u32 mask = ~((~(u32)0) << blocks); + + mask <<= block_idx % 32; + g.dbr_map[block_idx / 32] &= ~mask; +} + +/* -------------------------------------------------------------------------- */ + +static u32 dim2_read_ctr(u32 ctr_addr, u16 mdat_idx) +{ + DIMCB_IoWrite(&g.dim2->MADR, ctr_addr); + + /* wait till transfer is completed */ + while ((DIMCB_IoRead(&g.dim2->MCTL) & 1) != 1) + continue; + + DIMCB_IoWrite(&g.dim2->MCTL, 0); /* clear transfer complete */ + + return DIMCB_IoRead((&g.dim2->MDAT0) + mdat_idx); +} + +static void dim2_write_ctr_mask(u32 ctr_addr, const u32 *mask, const u32 *value) +{ + enum { MADR_WNR_BIT = 31 }; + + DIMCB_IoWrite(&g.dim2->MCTL, 0); /* clear transfer complete */ + + if (mask[0] != 0) + DIMCB_IoWrite(&g.dim2->MDAT0, value[0]); + if (mask[1] != 0) + DIMCB_IoWrite(&g.dim2->MDAT1, value[1]); + if (mask[2] != 0) + DIMCB_IoWrite(&g.dim2->MDAT2, value[2]); + if (mask[3] != 0) + DIMCB_IoWrite(&g.dim2->MDAT3, value[3]); + + DIMCB_IoWrite(&g.dim2->MDWE0, mask[0]); + DIMCB_IoWrite(&g.dim2->MDWE1, mask[1]); + DIMCB_IoWrite(&g.dim2->MDWE2, mask[2]); + DIMCB_IoWrite(&g.dim2->MDWE3, mask[3]); + + DIMCB_IoWrite(&g.dim2->MADR, bit_mask(MADR_WNR_BIT) | ctr_addr); + + /* wait till transfer is completed */ + while ((DIMCB_IoRead(&g.dim2->MCTL) & 1) != 1) + continue; + + DIMCB_IoWrite(&g.dim2->MCTL, 0); /* clear transfer complete */ +} + +static inline void dim2_write_ctr(u32 ctr_addr, const u32 *value) +{ + u32 const mask[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + + dim2_write_ctr_mask(ctr_addr, mask, value); +} + +static inline void dim2_clear_ctr(u32 ctr_addr) +{ + u32 const value[4] = { 0, 0, 0, 0 }; + + dim2_write_ctr(ctr_addr, value); +} + +static void dim2_configure_cat(u8 cat_base, u8 ch_addr, u8 ch_type, + bool read_not_write, bool sync_mfe) +{ + u16 const cat = + (read_not_write << CAT_RNW_BIT) | + (ch_type << CAT_CT_SHIFT) | + (ch_addr << CAT_CL_SHIFT) | + (sync_mfe << CAT_MFE_BIT) | + (false << CAT_MT_BIT) | + (true << CAT_CE_BIT); + u8 const ctr_addr = cat_base + ch_addr / 8; + u8 const idx = (ch_addr % 8) / 2; + u8 const shift = (ch_addr % 2) * 16; + u32 mask[4] = { 0, 0, 0, 0 }; + u32 value[4] = { 0, 0, 0, 0 }; + + mask[idx] = (u32)0xFFFF << shift; + value[idx] = cat << shift; + dim2_write_ctr_mask(ctr_addr, mask, value); +} + +static void dim2_clear_cat(u8 cat_base, u8 ch_addr) +{ + u8 const ctr_addr = cat_base + ch_addr / 8; + u8 const idx = (ch_addr % 8) / 2; + u8 const shift = (ch_addr % 2) * 16; + u32 mask[4] = { 0, 0, 0, 0 }; + u32 value[4] = { 0, 0, 0, 0 }; + + mask[idx] = (u32)0xFFFF << shift; + dim2_write_ctr_mask(ctr_addr, mask, value); +} + +static void dim2_configure_cdt(u8 ch_addr, u16 dbr_address, u16 hw_buffer_size, + u16 packet_length) +{ + u32 cdt[4] = { 0, 0, 0, 0 }; + + if (packet_length) + cdt[1] = ((packet_length - 1) << CDT1_BS_ISOC_SHIFT); + + cdt[3] = + ((hw_buffer_size - 1) << CDT3_BD_SHIFT) | + (dbr_address << CDT3_BA_SHIFT); + dim2_write_ctr(CDT + ch_addr, cdt); +} + +static void dim2_clear_cdt(u8 ch_addr) +{ + u32 cdt[4] = { 0, 0, 0, 0 }; + + dim2_write_ctr(CDT + ch_addr, cdt); +} + +static void dim2_configure_adt(u8 ch_addr) +{ + u32 adt[4] = { 0, 0, 0, 0 }; + + adt[0] = + (true << ADT0_CE_BIT) | + (true << ADT0_LE_BIT) | + (0 << ADT0_PG_BIT); + + dim2_write_ctr(ADT + ch_addr, adt); +} + +static void dim2_clear_adt(u8 ch_addr) +{ + u32 adt[4] = { 0, 0, 0, 0 }; + + dim2_write_ctr(ADT + ch_addr, adt); +} + +static void dim2_start_ctrl_async(u8 ch_addr, u8 idx, u32 buf_addr, + u16 buffer_size) +{ + u8 const shift = idx * 16; + + u32 mask[4] = { 0, 0, 0, 0 }; + u32 adt[4] = { 0, 0, 0, 0 }; + + mask[1] = + bit_mask(ADT1_PS_BIT + shift) | + bit_mask(ADT1_RDY_BIT + shift) | + (ADT1_CTRL_ASYNC_BD_MASK << (ADT1_BD_SHIFT + shift)); + adt[1] = + (true << (ADT1_PS_BIT + shift)) | + (true << (ADT1_RDY_BIT + shift)) | + ((buffer_size - 1) << (ADT1_BD_SHIFT + shift)); + + mask[idx + 2] = 0xFFFFFFFF; + adt[idx + 2] = buf_addr; + + dim2_write_ctr_mask(ADT + ch_addr, mask, adt); +} + +static void dim2_start_isoc_sync(u8 ch_addr, u8 idx, u32 buf_addr, + u16 buffer_size) +{ + u8 const shift = idx * 16; + + u32 mask[4] = { 0, 0, 0, 0 }; + u32 adt[4] = { 0, 0, 0, 0 }; + + mask[1] = + bit_mask(ADT1_RDY_BIT + shift) | + (ADT1_ISOC_SYNC_BD_MASK << (ADT1_BD_SHIFT + shift)); + adt[1] = + (true << (ADT1_RDY_BIT + shift)) | + ((buffer_size - 1) << (ADT1_BD_SHIFT + shift)); + + mask[idx + 2] = 0xFFFFFFFF; + adt[idx + 2] = buf_addr; + + dim2_write_ctr_mask(ADT + ch_addr, mask, adt); +} + + +static void dim2_clear_ctram(void) +{ + u32 ctr_addr; + + for (ctr_addr = 0; ctr_addr < 0x90; ctr_addr++) + dim2_clear_ctr(ctr_addr); +} + +static void dim2_configure_channel( + u8 ch_addr, u8 type, u8 is_tx, u16 dbr_address, u16 hw_buffer_size, + u16 packet_length, bool sync_mfe) +{ + dim2_configure_cdt(ch_addr, dbr_address, hw_buffer_size, packet_length); + dim2_configure_cat(MLB_CAT, ch_addr, type, is_tx ? 1 : 0, sync_mfe); + + dim2_configure_adt(ch_addr); + dim2_configure_cat(AHB_CAT, ch_addr, type, is_tx ? 0 : 1, sync_mfe); + + /* unmask interrupt for used channel, enable mlb_sys_int[0] interrupt */ + DIMCB_IoWrite(&g.dim2->ACMR0, + DIMCB_IoRead(&g.dim2->ACMR0) | bit_mask(ch_addr)); +} + +static void dim2_clear_channel(u8 ch_addr) +{ + /* mask interrupt for used channel, disable mlb_sys_int[0] interrupt */ + DIMCB_IoWrite(&g.dim2->ACMR0, + DIMCB_IoRead(&g.dim2->ACMR0) & ~bit_mask(ch_addr)); + + dim2_clear_cat(AHB_CAT, ch_addr); + dim2_clear_adt(ch_addr); + + dim2_clear_cat(MLB_CAT, ch_addr); + dim2_clear_cdt(ch_addr); +} + +/* -------------------------------------------------------------------------- */ +/* channel state helpers */ + +static void state_init(struct int_ch_state *state) +{ + state->request_counter = 0; + state->service_counter = 0; + + state->idx1 = 0; + state->idx2 = 0; + state->level = 0; +} + +/* -------------------------------------------------------------------------- */ +/* macro helper functions */ + +static inline bool check_channel_address(u32 ch_address) +{ + return ch_address > 0 && (ch_address % 2) == 0 && + (ch_address / 2) <= (u32)CAT_CL_MASK; +} + +static inline bool check_packet_length(u32 packet_length) +{ + u16 const max_size = ((u16)CDT3_BD_ISOC_MASK + 1u) / ISOC_DBR_FACTOR; + + if (packet_length <= 0) + return false; /* too small */ + + if (packet_length > max_size) + return false; /* too big */ + + if (packet_length - 1u > (u32)CDT1_BS_ISOC_MASK) + return false; /* too big */ + + return true; +} + +static inline bool check_bytes_per_frame(u32 bytes_per_frame) +{ + u16 const max_size = ((u16)CDT3_BD_MASK + 1u) / SYNC_DBR_FACTOR; + + if (bytes_per_frame <= 0) + return false; /* too small */ + + if (bytes_per_frame > max_size) + return false; /* too big */ + + return true; +} + +static inline u16 norm_ctrl_async_buffer_size(u16 buf_size) +{ + u16 const max_size = (u16)ADT1_CTRL_ASYNC_BD_MASK + 1u; + + if (buf_size > max_size) + return max_size; + + return buf_size; +} + +static inline u16 norm_isoc_buffer_size(u16 buf_size, u16 packet_length) +{ + u16 n; + u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u; + + if (buf_size > max_size) + buf_size = max_size; + + n = buf_size / packet_length; + + if (n < 2u) + return 0; /* too small buffer for given packet_length */ + + return packet_length * n; +} + +static inline u16 norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame) +{ + u16 n; + u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u; + u32 const unit = bytes_per_frame * (u16)FRAMES_PER_SUBBUFF; + + if (buf_size > max_size) + buf_size = max_size; + + n = buf_size / unit; + + if (n < 1u) + return 0; /* too small buffer for given bytes_per_frame */ + + return unit * n; +} + +static void dim2_cleanup(void) +{ + /* disable MediaLB */ + DIMCB_IoWrite(&g.dim2->MLBC0, false << MLBC0_MLBEN_BIT); + + dim2_clear_ctram(); + + /* disable mlb_int interrupt */ + DIMCB_IoWrite(&g.dim2->MIEN, 0); + + /* clear status for all dma channels */ + DIMCB_IoWrite(&g.dim2->ACSR0, 0xFFFFFFFF); + DIMCB_IoWrite(&g.dim2->ACSR1, 0xFFFFFFFF); + + /* mask interrupts for all channels */ + DIMCB_IoWrite(&g.dim2->ACMR0, 0); + DIMCB_IoWrite(&g.dim2->ACMR1, 0); +} + +static void dim2_initialize(bool enable_6pin, u8 mlb_clock) +{ + dim2_cleanup(); + + /* configure and enable MediaLB */ + DIMCB_IoWrite(&g.dim2->MLBC0, + enable_6pin << MLBC0_MLBPEN_BIT | + mlb_clock << MLBC0_MLBCLK_SHIFT | + MLBC0_FCNT_VAL(FRAMES_PER_SUBBUFF) << MLBC0_FCNT_SHIFT | + true << MLBC0_MLBEN_BIT); + + /* activate all HBI channels */ + DIMCB_IoWrite(&g.dim2->HCMR0, 0xFFFFFFFF); + DIMCB_IoWrite(&g.dim2->HCMR1, 0xFFFFFFFF); + + /* enable HBI */ + DIMCB_IoWrite(&g.dim2->HCTL, bit_mask(HCTL_EN_BIT)); + + /* configure DMA */ + DIMCB_IoWrite(&g.dim2->ACTL, + ACTL_DMA_MODE_VAL_DMA_MODE_1 << ACTL_DMA_MODE_BIT | + true << ACTL_SCE_BIT); + +#if 0 + DIMCB_IoWrite(&g.dim2->MIEN, + bit_mask(MIEN_CTX_BREAK_BIT) | + bit_mask(MIEN_CTX_PE_BIT) | + bit_mask(MIEN_CTX_DONE_BIT) | + bit_mask(MIEN_CRX_BREAK_BIT) | + bit_mask(MIEN_CRX_PE_BIT) | + bit_mask(MIEN_CRX_DONE_BIT) | + bit_mask(MIEN_ATX_BREAK_BIT) | + bit_mask(MIEN_ATX_PE_BIT) | + bit_mask(MIEN_ATX_DONE_BIT) | + bit_mask(MIEN_ARX_BREAK_BIT) | + bit_mask(MIEN_ARX_PE_BIT) | + bit_mask(MIEN_ARX_DONE_BIT)); +#endif +} + +static bool dim2_is_mlb_locked(void) +{ + u32 const mask0 = bit_mask(MLBC0_MLBLK_BIT); + u32 const mask1 = bit_mask(MLBC1_CLKMERR_BIT) | + bit_mask(MLBC1_LOCKERR_BIT); + u32 const c1 = DIMCB_IoRead(&g.dim2->MLBC1); + u32 const nda_mask = (u32)MLBC1_NDA_MASK << MLBC1_NDA_SHIFT; + + DIMCB_IoWrite(&g.dim2->MLBC1, c1 & nda_mask); + return (DIMCB_IoRead(&g.dim2->MLBC1) & mask1) == 0 && + (DIMCB_IoRead(&g.dim2->MLBC0) & mask0) != 0; +} + + +/* -------------------------------------------------------------------------- */ +/* channel help routines */ + +static inline bool service_channel(u8 ch_addr, u8 idx) +{ + u8 const shift = idx * 16; + u32 const adt1 = dim2_read_ctr(ADT + ch_addr, 1); + + if (((adt1 >> (ADT1_DNE_BIT + shift)) & 1) == 0) + return false; + + { + u32 mask[4] = { 0, 0, 0, 0 }; + u32 adt_w[4] = { 0, 0, 0, 0 }; + + mask[1] = + bit_mask(ADT1_DNE_BIT + shift) | + bit_mask(ADT1_ERR_BIT + shift) | + bit_mask(ADT1_RDY_BIT + shift); + dim2_write_ctr_mask(ADT + ch_addr, mask, adt_w); + } + + /* clear channel status bit */ + DIMCB_IoWrite(&g.dim2->ACSR0, bit_mask(ch_addr)); + + return true; +} + + +/* -------------------------------------------------------------------------- */ +/* channel init routines */ + +static void isoc_init(struct dim_channel *ch, u8 ch_addr, u16 packet_length) +{ + state_init(&ch->state); + + ch->addr = ch_addr; + + ch->packet_length = packet_length; + ch->bytes_per_frame = 0; + ch->done_sw_buffers_number = 0; +} + +static void sync_init(struct dim_channel *ch, u8 ch_addr, u16 bytes_per_frame) +{ + state_init(&ch->state); + + ch->addr = ch_addr; + + ch->packet_length = 0; + ch->bytes_per_frame = bytes_per_frame; + ch->done_sw_buffers_number = 0; +} + +static void channel_init(struct dim_channel *ch, u8 ch_addr) +{ + state_init(&ch->state); + + ch->addr = ch_addr; + + ch->packet_length = 0; + ch->bytes_per_frame = 0; + ch->done_sw_buffers_number = 0; +} + +/* returns true if channel interrupt state is cleared */ +static bool channel_service_interrupt(struct dim_channel *ch) +{ + struct int_ch_state *const state = &ch->state; + + if (!service_channel(ch->addr, state->idx2)) + return false; + + state->idx2 ^= 1; + state->request_counter++; + return true; +} + +static bool channel_start(struct dim_channel *ch, u32 buf_addr, u16 buf_size) +{ + struct int_ch_state *const state = &ch->state; + + if (buf_size <= 0) + return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, "Bad buffer size"); + + if (ch->packet_length == 0 && ch->bytes_per_frame == 0 && + buf_size != norm_ctrl_async_buffer_size(buf_size)) + return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, + "Bad control/async buffer size"); + + if (ch->packet_length && + buf_size != norm_isoc_buffer_size(buf_size, ch->packet_length)) + return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, + "Bad isochronous buffer size"); + + if (ch->bytes_per_frame && + buf_size != norm_sync_buffer_size(buf_size, ch->bytes_per_frame)) + return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, + "Bad synchronous buffer size"); + + if (state->level >= 2u) + return dim_on_error(DIM_ERR_OVERFLOW, "Channel overflow"); + + ++state->level; + + if (ch->packet_length || ch->bytes_per_frame) + dim2_start_isoc_sync(ch->addr, state->idx1, buf_addr, buf_size); + else + dim2_start_ctrl_async(ch->addr, state->idx1, buf_addr, buf_size); + state->idx1 ^= 1; + + return true; +} + +static u8 channel_service(struct dim_channel *ch) +{ + struct int_ch_state *const state = &ch->state; + + if (state->service_counter != state->request_counter) { + state->service_counter++; + if (state->level == 0) + return DIM_ERR_UNDERFLOW; + + --state->level; + ch->done_sw_buffers_number++; + } + + return DIM_NO_ERROR; +} + +static bool channel_detach_buffers(struct dim_channel *ch, u16 buffers_number) +{ + if (buffers_number > ch->done_sw_buffers_number) + return dim_on_error(DIM_ERR_UNDERFLOW, "Channel underflow"); + + ch->done_sw_buffers_number -= buffers_number; + return true; +} + + +/* -------------------------------------------------------------------------- */ +/* API */ + +u8 DIM_Startup(void *dim_base_address, u32 mlb_clock) +{ + g.dim_is_initialized = false; + + if (!dim_base_address) + return DIM_INIT_ERR_DIM_ADDR; + + /* MediaLB clock: 0 - 256 fs, 1 - 512 fs, 2 - 1024 fs, 3 - 2048 fs */ + /* MediaLB clock: 4 - 3072 fs, 5 - 4096 fs, 6 - 6144 fs, 7 - 8192 fs */ + if (mlb_clock >= 8) + return DIM_INIT_ERR_MLB_CLOCK; + + g.dim2 = dim_base_address; + g.dbr_map[0] = g.dbr_map[1] = 0; + + dim2_initialize(mlb_clock >= 3, mlb_clock); + + g.dim_is_initialized = true; + + return DIM_NO_ERROR; +} + +void DIM_Shutdown(void) +{ + g.dim_is_initialized = false; + dim2_cleanup(); +} + +bool DIM_GetLockState(void) +{ + return dim2_is_mlb_locked(); +} + +static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx, + u16 ch_address, u16 hw_buffer_size) +{ + if (!g.dim_is_initialized || !ch) + return DIM_ERR_DRIVER_NOT_INITIALIZED; + + if (!check_channel_address(ch_address)) + return DIM_INIT_ERR_CHANNEL_ADDRESS; + + ch->dbr_size = hw_buffer_size; + ch->dbr_addr = alloc_dbr(ch->dbr_size); + if (ch->dbr_addr >= DBR_SIZE) + return DIM_INIT_ERR_OUT_OF_MEMORY; + + channel_init(ch, ch_address / 2); + + dim2_configure_channel(ch->addr, type, is_tx, + ch->dbr_addr, ch->dbr_size, 0, false); + + return DIM_NO_ERROR; +} + +u16 DIM_NormCtrlAsyncBufferSize(u16 buf_size) +{ + return norm_ctrl_async_buffer_size(buf_size); +} + +/** + * Retrieves maximal possible correct buffer size for isochronous data type + * conform to given packet length and not bigger than given buffer size. + * + * Returns non-zero correct buffer size or zero by error. + */ +u16 DIM_NormIsocBufferSize(u16 buf_size, u16 packet_length) +{ + if (!check_packet_length(packet_length)) + return 0; + + return norm_isoc_buffer_size(buf_size, packet_length); +} + +/** + * Retrieves maximal possible correct buffer size for synchronous data type + * conform to given bytes per frame and not bigger than given buffer size. + * + * Returns non-zero correct buffer size or zero by error. + */ +u16 DIM_NormSyncBufferSize(u16 buf_size, u16 bytes_per_frame) +{ + if (!check_bytes_per_frame(bytes_per_frame)) + return 0; + + return norm_sync_buffer_size(buf_size, bytes_per_frame); +} + +u8 DIM_InitControl(struct dim_channel *ch, u8 is_tx, u16 ch_address, + u16 max_buffer_size) +{ + return init_ctrl_async(ch, CAT_CT_VAL_CONTROL, is_tx, ch_address, + max_buffer_size * 2); +} + +u8 DIM_InitAsync(struct dim_channel *ch, u8 is_tx, u16 ch_address, + u16 max_buffer_size) +{ + return init_ctrl_async(ch, CAT_CT_VAL_ASYNC, is_tx, ch_address, + max_buffer_size * 2); +} + +u8 DIM_InitIsoc(struct dim_channel *ch, u8 is_tx, u16 ch_address, + u16 packet_length) +{ + if (!g.dim_is_initialized || !ch) + return DIM_ERR_DRIVER_NOT_INITIALIZED; + + if (!check_channel_address(ch_address)) + return DIM_INIT_ERR_CHANNEL_ADDRESS; + + if (!check_packet_length(packet_length)) + return DIM_ERR_BAD_CONFIG; + + ch->dbr_size = packet_length * ISOC_DBR_FACTOR; + ch->dbr_addr = alloc_dbr(ch->dbr_size); + if (ch->dbr_addr >= DBR_SIZE) + return DIM_INIT_ERR_OUT_OF_MEMORY; + + isoc_init(ch, ch_address / 2, packet_length); + + dim2_configure_channel(ch->addr, CAT_CT_VAL_ISOC, is_tx, ch->dbr_addr, + ch->dbr_size, packet_length, false); + + return DIM_NO_ERROR; +} + +u8 DIM_InitSync(struct dim_channel *ch, u8 is_tx, u16 ch_address, + u16 bytes_per_frame) +{ + if (!g.dim_is_initialized || !ch) + return DIM_ERR_DRIVER_NOT_INITIALIZED; + + if (!check_channel_address(ch_address)) + return DIM_INIT_ERR_CHANNEL_ADDRESS; + + if (!check_bytes_per_frame(bytes_per_frame)) + return DIM_ERR_BAD_CONFIG; + + ch->dbr_size = bytes_per_frame * SYNC_DBR_FACTOR; + ch->dbr_addr = alloc_dbr(ch->dbr_size); + if (ch->dbr_addr >= DBR_SIZE) + return DIM_INIT_ERR_OUT_OF_MEMORY; + + sync_init(ch, ch_address / 2, bytes_per_frame); + + dim2_configure_channel(ch->addr, CAT_CT_VAL_SYNC, is_tx, + ch->dbr_addr, ch->dbr_size, 0, true); + + return DIM_NO_ERROR; +} + +u8 DIM_DestroyChannel(struct dim_channel *ch) +{ + if (!g.dim_is_initialized || !ch) + return DIM_ERR_DRIVER_NOT_INITIALIZED; + + dim2_clear_channel(ch->addr); + if (ch->dbr_addr < DBR_SIZE) + free_dbr(ch->dbr_addr, ch->dbr_size); + ch->dbr_addr = DBR_SIZE; + + return DIM_NO_ERROR; +} + +void DIM_ServiceIrq(struct dim_channel *const *channels) +{ + bool state_changed; + + if (!g.dim_is_initialized) { + dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, + "DIM is not initialized"); + return; + } + + if (!channels) { + dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, "Bad channels"); + return; + } + + /* + * Use while-loop and a flag to make sure the age is changed back at least once, + * otherwise the interrupt may never come if CPU generates interrupt on changing age. + * + * This cycle runs not more than number of channels, because service_interrupts + * routine doesn't start the channel again. + */ + do { + struct dim_channel *const *ch = channels; + + state_changed = false; + + while (*ch) { + state_changed |= channel_service_interrupt(*ch); + ++ch; + } + } while (state_changed); + + /* clear pending Interrupts */ + DIMCB_IoWrite(&g.dim2->MS0, 0); + DIMCB_IoWrite(&g.dim2->MS1, 0); +} + +u8 DIM_ServiceChannel(struct dim_channel *ch) +{ + if (!g.dim_is_initialized || !ch) + return DIM_ERR_DRIVER_NOT_INITIALIZED; + + return channel_service(ch); +} + +struct dim_ch_state_t *DIM_GetChannelState(struct dim_channel *ch, + struct dim_ch_state_t *state_ptr) +{ + if (!ch || !state_ptr) + return 0; + + state_ptr->ready = ch->state.level < 2; + state_ptr->done_buffers = ch->done_sw_buffers_number; + + return state_ptr; +} + +bool DIM_EnqueueBuffer(struct dim_channel *ch, u32 buffer_addr, u16 buffer_size) +{ + if (!ch) + return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, "Bad channel"); + + return channel_start(ch, buffer_addr, buffer_size); +} + +bool DIM_DetachBuffers(struct dim_channel *ch, u16 buffers_number) +{ + if (!ch) + return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, "Bad channel"); + + return channel_detach_buffers(ch, buffers_number); +} + +u32 DIM_ReadRegister(u8 register_index) +{ + return DIMCB_IoRead((u32 *)g.dim2 + register_index); +} diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.h b/drivers/staging/most/hdm-dim2/dim2_hal.h new file mode 100644 index 000000000000..d88b5a0e3244 --- /dev/null +++ b/drivers/staging/most/hdm-dim2/dim2_hal.h @@ -0,0 +1,124 @@ +/* + * dim2_hal.h - DIM2 HAL interface + * (MediaLB, Device Interface Macro IP, OS62420) + * + * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This file is licensed under GPLv2. + */ + +#ifndef _DIM2_HAL_H +#define _DIM2_HAL_H + +#include <linux/types.h> + + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The values below are specified in the hardware specification. + * So, they should not be changed until the hardware specification changes. + */ +enum mlb_clk_speed { + CLK_256FS = 0, + CLK_512FS = 1, + CLK_1024FS = 2, + CLK_2048FS = 3, + CLK_3072FS = 4, + CLK_4096FS = 5, + CLK_6144FS = 6, + CLK_8192FS = 7, +}; + +struct dim_ch_state_t { + bool ready; /* Shows readiness to enqueue next buffer */ + u16 done_buffers; /* Number of completed buffers */ +}; + +typedef int atomic_counter_t; + +struct int_ch_state { + /* changed only in interrupt context */ + volatile atomic_counter_t request_counter; + + /* changed only in task context */ + volatile atomic_counter_t service_counter; + + u8 idx1; + u8 idx2; + u8 level; /* [0..2], buffering level */ +}; + +struct dim_channel { + struct int_ch_state state; + u8 addr; + u16 dbr_addr; + u16 dbr_size; + u16 packet_length; /*< Isochronous packet length in bytes. */ + u16 bytes_per_frame; /*< Synchronous bytes per frame. */ + u16 done_sw_buffers_number; /*< Done software buffers number. */ +}; + + +u8 DIM_Startup(void *dim_base_address, u32 mlb_clock); + +void DIM_Shutdown(void); + +bool DIM_GetLockState(void); + +u16 DIM_NormCtrlAsyncBufferSize(u16 buf_size); + +u16 DIM_NormIsocBufferSize(u16 buf_size, u16 packet_length); + +u16 DIM_NormSyncBufferSize(u16 buf_size, u16 bytes_per_frame); + +u8 DIM_InitControl(struct dim_channel *ch, u8 is_tx, u16 ch_address, + u16 max_buffer_size); + +u8 DIM_InitAsync(struct dim_channel *ch, u8 is_tx, u16 ch_address, + u16 max_buffer_size); + +u8 DIM_InitIsoc(struct dim_channel *ch, u8 is_tx, u16 ch_address, + u16 packet_length); + +u8 DIM_InitSync(struct dim_channel *ch, u8 is_tx, u16 ch_address, + u16 bytes_per_frame); + +u8 DIM_DestroyChannel(struct dim_channel *ch); + +void DIM_ServiceIrq(struct dim_channel *const *channels); + +u8 DIM_ServiceChannel(struct dim_channel *ch); + +struct dim_ch_state_t *DIM_GetChannelState(struct dim_channel *ch, + struct dim_ch_state_t *dim_ch_state_ptr); + +bool DIM_EnqueueBuffer(struct dim_channel *ch, u32 buffer_addr, + u16 buffer_size); + +bool DIM_DetachBuffers(struct dim_channel *ch, u16 buffers_number); + +u32 DIM_ReadRegister(u8 register_index); + + +extern u32 DIMCB_IoRead(u32 *ptr32); + +extern void DIMCB_IoWrite(u32 *ptr32, u32 value); + +extern void DIMCB_OnError(u8 error_id, const char *error_message); + +extern void DIMCB_OnFail(const char *filename, int linenum); + + +#ifdef __cplusplus +} +#endif + +#endif /* _DIM2_HAL_H */ diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c new file mode 100644 index 000000000000..6a5a3a2775f3 --- /dev/null +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c @@ -0,0 +1,964 @@ +/* + * dim2_hdm.c - MediaLB DIM2 Hardware Dependent Module + * + * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This file is licensed under GPLv2. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/module.h> +#include <linux/printk.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/slab.h> +#include <linux/io.h> +#include <linux/dma-mapping.h> +#include <linux/sched.h> +#include <linux/kthread.h> + +#include <mostcore.h> +#include <networking.h> +#include "dim2_hal.h" +#include "dim2_hdm.h" +#include "dim2_errors.h" +#include "dim2_sysfs.h" + +#define DMA_CHANNELS (32 - 1) /* channel 0 is a system channel */ + +#define MAX_BUFFERS_PACKET 32 +#define MAX_BUFFERS_STREAMING 32 +#define MAX_BUF_SIZE_PACKET 2048 +#define MAX_BUF_SIZE_STREAMING (8*1024) + +/* command line parameter to select clock speed */ +static char *clock_speed; +module_param(clock_speed, charp, 0); +MODULE_PARM_DESC(clock_speed, "MediaLB Clock Speed"); + +/* + * ############################################################################# + * + * The define below activates an utility function used by HAL-simu + * for calling DIM interrupt handler. + * It is used only for TEST PURPOSE and shall be commented before release. + * + * ############################################################################# + */ +/* #define ENABLE_HDM_TEST */ + +static DEFINE_SPINLOCK(dim_lock); + +static void dim2_tasklet_fn(unsigned long data); +static DECLARE_TASKLET(dim2_tasklet, dim2_tasklet_fn, 0); + +/** + * struct hdm_channel - private structure to keep channel specific data + * @is_initialized: identifier to know whether the channel is initialized + * @ch: HAL specific channel data + * @pending_list: list to keep MBO's before starting transfer + * @started_list: list to keep MBO's after starting transfer + * @direction: channel direction (TX or RX) + * @data_type: channel data type + */ +struct hdm_channel { + char name[sizeof "caNNN"]; + bool is_initialized; + struct dim_channel ch; + struct list_head pending_list; /* before DIM_EnqueueBuffer() */ + struct list_head started_list; /* after DIM_EnqueueBuffer() */ + enum most_channel_direction direction; + enum most_channel_data_type data_type; +}; + +/** + * struct dim2_hdm - private structure to keep interface specific data + * @hch: an array of channel specific data + * @most_iface: most interface structure + * @capabilities: an array of channel capability data + * @io_base: I/O register base address + * @irq_ahb0: dim2 AHB0 irq number + * @clk_speed: user selectable (through command line parameter) clock speed + * @netinfo_task: thread to deliver network status + * @netinfo_waitq: waitq for the thread to sleep + * @deliver_netinfo: to identify whether network status received + * @mac_addrs: INIC mac address + * @link_state: network link state + * @atx_idx: index of async tx channel + */ +struct dim2_hdm { + struct hdm_channel hch[DMA_CHANNELS]; + struct most_channel_capability capabilities[DMA_CHANNELS]; + struct most_interface most_iface; + char name[16 + sizeof "dim2-"]; + void *io_base; + unsigned int irq_ahb0; + int clk_speed; + struct task_struct *netinfo_task; + wait_queue_head_t netinfo_waitq; + int deliver_netinfo; + unsigned char mac_addrs[6]; + unsigned char link_state; + int atx_idx; + struct medialb_bus bus; +}; + +#define iface_to_hdm(iface) container_of(iface, struct dim2_hdm, most_iface) + +/* Macro to identify a network status message */ +#define PACKET_IS_NET_INFO(p) \ + (((p)[1] == 0x18) && ((p)[2] == 0x05) && ((p)[3] == 0x0C) && \ + ((p)[13] == 0x3C) && ((p)[14] == 0x00) && ((p)[15] == 0x0A)) + +#if defined(ENABLE_HDM_TEST) +static struct dim2_hdm *test_dev; +#endif + +bool dim2_sysfs_get_state_cb(void) +{ + bool state; + unsigned long flags; + + spin_lock_irqsave(&dim_lock, flags); + state = DIM_GetLockState(); + spin_unlock_irqrestore(&dim_lock, flags); + + return state; +} + +/** + * DIMCB_IoRead - callback from HAL to read an I/O register + * @ptr32: register address + */ +u32 DIMCB_IoRead(u32 *ptr32) +{ + return __raw_readl(ptr32); +} + +/** + * DIMCB_IoWrite - callback from HAL to write value to an I/O register + * @ptr32: register address + * @value: value to write + */ +void DIMCB_IoWrite(u32 *ptr32, u32 value) +{ + __raw_writel(value, ptr32); +} + +/** + * DIMCB_OnError - callback from HAL to report miscommunication between + * HDM and HAL + * @error_id: Error ID + * @error_message: Error message. Some text in a free format + */ +void DIMCB_OnError(u8 error_id, const char *error_message) +{ + pr_err("DIMCB_OnError: error_id - %d, error_message - %s\n", error_id, + error_message); +} + +/** + * DIMCB_OnFail - callback from HAL to report unrecoverable errors + * @filename: Source file where the error happened + * @linenum: Line number of the file where the error happened + */ +void DIMCB_OnFail(const char *filename, int linenum) +{ + pr_err("DIMCB_OnFail: file - %s, line no. - %d\n", filename, linenum); +} + +/** + * startup_dim - initialize the dim2 interface + * @pdev: platform device + * + * Get the value of command line parameter "clock_speed" if given or use the + * default value, enable the clock and PLL, and initialize the dim2 interface. + */ +static int startup_dim(struct platform_device *pdev) +{ + struct dim2_hdm *dev = platform_get_drvdata(pdev); + struct dim2_platform_data *pdata = pdev->dev.platform_data; + u8 hal_ret; + + dev->clk_speed = -1; + + if (clock_speed) { + if (!strcmp(clock_speed, "256fs")) + dev->clk_speed = CLK_256FS; + else if (!strcmp(clock_speed, "512fs")) + dev->clk_speed = CLK_512FS; + else if (!strcmp(clock_speed, "1024fs")) + dev->clk_speed = CLK_1024FS; + else if (!strcmp(clock_speed, "2048fs")) + dev->clk_speed = CLK_2048FS; + else if (!strcmp(clock_speed, "3072fs")) + dev->clk_speed = CLK_3072FS; + else if (!strcmp(clock_speed, "4096fs")) + dev->clk_speed = CLK_4096FS; + else if (!strcmp(clock_speed, "6144fs")) + dev->clk_speed = CLK_6144FS; + else if (!strcmp(clock_speed, "8192fs")) + dev->clk_speed = CLK_8192FS; + } + + if (dev->clk_speed == -1) { + pr_info("Bad or missing clock speed parameter," + " using default value: 3072fs\n"); + dev->clk_speed = CLK_3072FS; + } else + pr_info("Selected clock speed: %s\n", clock_speed); + + if (pdata && pdata->init) { + int ret = pdata->init(pdata, dev->io_base, dev->clk_speed); + + if (ret) + return ret; + } + + hal_ret = DIM_Startup(dev->io_base, dev->clk_speed); + if (hal_ret != DIM_NO_ERROR) { + pr_err("DIM_Startup failed: %d\n", hal_ret); + if (pdata && pdata->destroy) + pdata->destroy(pdata); + return -ENODEV; + } + + return 0; +} + +/** + * try_start_dim_transfer - try to transfer a buffer on a channel + * @hdm_ch: channel specific data + * + * Transfer a buffer from pending_list if the channel is ready + */ +static int try_start_dim_transfer(struct hdm_channel *hdm_ch) +{ + u16 buf_size; + struct list_head *head = &hdm_ch->pending_list; + struct mbo *mbo; + unsigned long flags; + struct dim_ch_state_t st; + + BUG_ON(hdm_ch == 0); + BUG_ON(!hdm_ch->is_initialized); + + spin_lock_irqsave(&dim_lock, flags); + if (list_empty(head)) { + spin_unlock_irqrestore(&dim_lock, flags); + return -EAGAIN; + } + + if (!DIM_GetChannelState(&hdm_ch->ch, &st)->ready) { + spin_unlock_irqrestore(&dim_lock, flags); + return -EAGAIN; + } + + mbo = list_entry(head->next, struct mbo, list); + buf_size = mbo->buffer_length; + + BUG_ON(mbo->bus_address == 0); + if (!DIM_EnqueueBuffer(&hdm_ch->ch, mbo->bus_address, buf_size)) { + list_del(head->next); + spin_unlock_irqrestore(&dim_lock, flags); + mbo->processed_length = 0; + mbo->status = MBO_E_INVAL; + mbo->complete(mbo); + return -EFAULT; + } + + list_move_tail(head->next, &hdm_ch->started_list); + spin_unlock_irqrestore(&dim_lock, flags); + + return 0; +} + +/** + * deliver_netinfo_thread - thread to deliver network status to mostcore + * @data: private data + * + * Wait for network status and deliver it to mostcore once it is received + */ +static int deliver_netinfo_thread(void *data) +{ + struct dim2_hdm *dev = (struct dim2_hdm *)data; + + while (!kthread_should_stop()) { + wait_event_interruptible(dev->netinfo_waitq, + dev->deliver_netinfo || + kthread_should_stop()); + + if (dev->deliver_netinfo) { + dev->deliver_netinfo--; + most_deliver_netinfo(&dev->most_iface, dev->link_state, + dev->mac_addrs); + } + } + + return 0; +} + +/** + * retrieve_netinfo - retrieve network status from received buffer + * @dev: private data + * @mbo: received MBO + * + * Parse the message in buffer and get node address, link state, MAC address. + * Wake up a thread to deliver this status to mostcore + */ +static void retrieve_netinfo(struct dim2_hdm *dev, struct mbo *mbo) +{ + u8 *data = mbo->virt_address; + u8 *mac = dev->mac_addrs; + + pr_info("Node Address: 0x%03x\n", (u16)data[16] << 8 | data[17]); + dev->link_state = data[18]; + pr_info("NIState: %d\n", dev->link_state); + memcpy(mac, data + 19, 6); + pr_info("MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + dev->deliver_netinfo++; + wake_up_interruptible(&dev->netinfo_waitq); +} + +/** + * service_done_flag - handle completed buffers + * @dev: private data + * @ch_idx: channel index + * + * Return back the completed buffers to mostcore, using completion callback + */ +static void service_done_flag(struct dim2_hdm *dev, int ch_idx) +{ + struct hdm_channel *hdm_ch = dev->hch + ch_idx; + struct dim_ch_state_t st; + struct list_head *head; + struct mbo *mbo; + int done_buffers; + unsigned long flags; + u8 *data; + + BUG_ON(hdm_ch == 0); + BUG_ON(!hdm_ch->is_initialized); + + spin_lock_irqsave(&dim_lock, flags); + + done_buffers = DIM_GetChannelState(&hdm_ch->ch, &st)->done_buffers; + if (!done_buffers) { + spin_unlock_irqrestore(&dim_lock, flags); + return; + } + + if (!DIM_DetachBuffers(&hdm_ch->ch, done_buffers)) { + spin_unlock_irqrestore(&dim_lock, flags); + return; + } + spin_unlock_irqrestore(&dim_lock, flags); + + head = &hdm_ch->started_list; + + while (done_buffers) { + spin_lock_irqsave(&dim_lock, flags); + if (list_empty(head)) { + spin_unlock_irqrestore(&dim_lock, flags); + pr_crit("hard error: started_mbo list is empty " + "whereas DIM2 has sent buffers\n"); + break; + } + + mbo = list_entry(head->next, struct mbo, list); + list_del(head->next); + spin_unlock_irqrestore(&dim_lock, flags); + + data = mbo->virt_address; + + if (hdm_ch->data_type == MOST_CH_ASYNC && + hdm_ch->direction == MOST_CH_RX && + PACKET_IS_NET_INFO(data)) { + + retrieve_netinfo(dev, mbo); + + spin_lock_irqsave(&dim_lock, flags); + list_add_tail(&mbo->list, &hdm_ch->pending_list); + spin_unlock_irqrestore(&dim_lock, flags); + } else { + if (hdm_ch->data_type == MOST_CH_CONTROL || + hdm_ch->data_type == MOST_CH_ASYNC) { + + u32 const data_size = + (u32)data[0] * 256 + data[1] + 2; + + mbo->processed_length = + min(data_size, (u32)mbo->buffer_length); + } else { + mbo->processed_length = mbo->buffer_length; + } + mbo->status = MBO_SUCCESS; + mbo->complete(mbo); + } + + done_buffers--; + } +} + +static struct dim_channel **get_active_channels(struct dim2_hdm *dev, + struct dim_channel **buffer) +{ + int idx = 0; + int ch_idx; + + for (ch_idx = 0; ch_idx < DMA_CHANNELS; ch_idx++) { + if (dev->hch[ch_idx].is_initialized) + buffer[idx++] = &dev->hch[ch_idx].ch; + } + buffer[idx++] = 0; + + return buffer; +} + +/** + * dim2_tasklet_fn - tasklet function + * @data: private data + * + * Service each initialized channel, if needed + */ +static void dim2_tasklet_fn(unsigned long data) +{ + struct dim2_hdm *dev = (struct dim2_hdm *)data; + unsigned long flags; + int ch_idx; + + for (ch_idx = 0; ch_idx < DMA_CHANNELS; ch_idx++) { + if (!dev->hch[ch_idx].is_initialized) + continue; + + spin_lock_irqsave(&dim_lock, flags); + DIM_ServiceChannel(&(dev->hch[ch_idx].ch)); + spin_unlock_irqrestore(&dim_lock, flags); + + service_done_flag(dev, ch_idx); + while (!try_start_dim_transfer(dev->hch + ch_idx)) + continue; + } +} + +/** + * dim2_ahb_isr - interrupt service routine + * @irq: irq number + * @_dev: private data + * + * Acknowledge the interrupt and schedule a tasklet to service channels. + * Return IRQ_HANDLED. + */ +static irqreturn_t dim2_ahb_isr(int irq, void *_dev) +{ + struct dim2_hdm *dev = (struct dim2_hdm *)_dev; + struct dim_channel *buffer[DMA_CHANNELS + 1]; + unsigned long flags; + + spin_lock_irqsave(&dim_lock, flags); + DIM_ServiceIrq(get_active_channels(dev, buffer)); + spin_unlock_irqrestore(&dim_lock, flags); + +#if !defined(ENABLE_HDM_TEST) + dim2_tasklet.data = (unsigned long)dev; + tasklet_schedule(&dim2_tasklet); +#else + dim2_tasklet_fn((unsigned long)dev); +#endif + return IRQ_HANDLED; +} + +#if defined(ENABLE_HDM_TEST) + +/* + * Utility function used by HAL-simu for calling DIM interrupt handler. + * It is used only for TEST PURPOSE. + */ +void raise_dim_interrupt(void) +{ + (void)dim2_ahb_isr(0, test_dev); +} +#endif + +/** + * complete_all_mbos - complete MBO's in a list + * @head: list head + * + * Delete all the entries in list and return back MBO's to mostcore using + * completion call back. + */ +static void complete_all_mbos(struct list_head *head) +{ + unsigned long flags; + struct mbo *mbo; + + for (;;) { + spin_lock_irqsave(&dim_lock, flags); + if (list_empty(head)) { + spin_unlock_irqrestore(&dim_lock, flags); + break; + } + + mbo = list_entry(head->next, struct mbo, list); + list_del(head->next); + spin_unlock_irqrestore(&dim_lock, flags); + + mbo->processed_length = 0; + mbo->status = MBO_E_CLOSE; + mbo->complete(mbo); + } +} + +/** + * configure_channel - initialize a channel + * @iface: interface the channel belongs to + * @channel: channel to be configured + * @channel_config: structure that holds the configuration information + * + * Receives configuration information from mostcore and initialize + * the corresponding channel. Return 0 on success, negative on failure. + */ +static int configure_channel(struct most_interface *most_iface, int ch_idx, + struct most_channel_config *ccfg) +{ + struct dim2_hdm *dev = iface_to_hdm(most_iface); + bool const is_tx = ccfg->direction == MOST_CH_TX; + u16 const sub_size = ccfg->subbuffer_size; + u16 const buf_size = ccfg->buffer_size; + u16 new_size; + unsigned long flags; + u8 hal_ret; + int const ch_addr = ch_idx * 2 + 2; + struct hdm_channel *const hdm_ch = dev->hch + ch_idx; + + BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS); + + if (hdm_ch->is_initialized) + return -EPERM; + + switch (ccfg->data_type) { + case MOST_CH_CONTROL: + new_size = DIM_NormCtrlAsyncBufferSize(buf_size); + if (new_size == 0) { + pr_err("%s: too small buffer size\n", hdm_ch->name); + return -EINVAL; + } + ccfg->buffer_size = new_size; + if (new_size != buf_size) + pr_warn("%s: fixed buffer size (%d -> %d)\n", + hdm_ch->name, buf_size, new_size); + spin_lock_irqsave(&dim_lock, flags); + hal_ret = DIM_InitControl(&hdm_ch->ch, is_tx, ch_addr, buf_size); + break; + case MOST_CH_ASYNC: + new_size = DIM_NormCtrlAsyncBufferSize(buf_size); + if (new_size == 0) { + pr_err("%s: too small buffer size\n", hdm_ch->name); + return -EINVAL; + } + ccfg->buffer_size = new_size; + if (new_size != buf_size) + pr_warn("%s: fixed buffer size (%d -> %d)\n", + hdm_ch->name, buf_size, new_size); + spin_lock_irqsave(&dim_lock, flags); + hal_ret = DIM_InitAsync(&hdm_ch->ch, is_tx, ch_addr, buf_size); + break; + case MOST_CH_ISOC_AVP: + new_size = DIM_NormIsocBufferSize(buf_size, sub_size); + if (new_size == 0) { + pr_err("%s: invalid sub-buffer size or " + "too small buffer size\n", hdm_ch->name); + return -EINVAL; + } + ccfg->buffer_size = new_size; + if (new_size != buf_size) + pr_warn("%s: fixed buffer size (%d -> %d)\n", + hdm_ch->name, buf_size, new_size); + spin_lock_irqsave(&dim_lock, flags); + hal_ret = DIM_InitIsoc(&hdm_ch->ch, is_tx, ch_addr, sub_size); + break; + case MOST_CH_SYNC: + new_size = DIM_NormSyncBufferSize(buf_size, sub_size); + if (new_size == 0) { + pr_err("%s: invalid sub-buffer size or " + "too small buffer size\n", hdm_ch->name); + return -EINVAL; + } + ccfg->buffer_size = new_size; + if (new_size != buf_size) + pr_warn("%s: fixed buffer size (%d -> %d)\n", + hdm_ch->name, buf_size, new_size); + spin_lock_irqsave(&dim_lock, flags); + hal_ret = DIM_InitSync(&hdm_ch->ch, is_tx, ch_addr, sub_size); + break; + default: + pr_err("%s: configure failed, bad channel type: %d\n", + hdm_ch->name, ccfg->data_type); + return -EINVAL; + } + + if (hal_ret != DIM_NO_ERROR) { + spin_unlock_irqrestore(&dim_lock, flags); + pr_err("%s: configure failed (%d), type: %d, is_tx: %d\n", + hdm_ch->name, hal_ret, ccfg->data_type, (int)is_tx); + return -ENODEV; + } + + hdm_ch->data_type = ccfg->data_type; + hdm_ch->direction = ccfg->direction; + hdm_ch->is_initialized = true; + + if (hdm_ch->data_type == MOST_CH_ASYNC && + hdm_ch->direction == MOST_CH_TX && + dev->atx_idx < 0) + dev->atx_idx = ch_idx; + + spin_unlock_irqrestore(&dim_lock, flags); + + return 0; +} + +/** + * enqueue - enqueue a buffer for data transfer + * @iface: intended interface + * @channel: ID of the channel the buffer is intended for + * @mbo: pointer to the buffer object + * + * Push the buffer into pending_list and try to transfer one buffer from + * pending_list. Return 0 on success, negative on failure. + */ +static int enqueue(struct most_interface *most_iface, int ch_idx, + struct mbo *mbo) +{ + struct dim2_hdm *dev = iface_to_hdm(most_iface); + struct hdm_channel *hdm_ch = dev->hch + ch_idx; + unsigned long flags; + + BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS); + + if (!hdm_ch->is_initialized) + return -EPERM; + + if (mbo->bus_address == 0) + return -EFAULT; + + spin_lock_irqsave(&dim_lock, flags); + list_add_tail(&mbo->list, &hdm_ch->pending_list); + spin_unlock_irqrestore(&dim_lock, flags); + + (void)try_start_dim_transfer(hdm_ch); + + return 0; +} + +/** + * request_netinfo - triggers retrieving of network info + * @iface: pointer to the interface + * @channel_id: corresponding channel ID + * + * Send a command to INIC which triggers retrieving of network info by means of + * "Message exchange over MDP/MEP". Return 0 on success, negative on failure. + */ +static void request_netinfo(struct most_interface *most_iface, int ch_idx) +{ + struct dim2_hdm *dev = iface_to_hdm(most_iface); + struct mbo *mbo; + u8 *data; + + if (dev->atx_idx < 0) { + pr_err("Async Tx Not initialized\n"); + return; + } + + mbo = most_get_mbo(&dev->most_iface, dev->atx_idx); + if (!mbo) + return; + + mbo->buffer_length = 5; + + data = mbo->virt_address; + + data[0] = 0x00; /* PML High byte */ + data[1] = 0x03; /* PML Low byte */ + data[2] = 0x02; /* PMHL */ + data[3] = 0x08; /* FPH */ + data[4] = 0x40; /* FMF (FIFO cmd msg - Triggers NAOverMDP) */ + + most_submit_mbo(mbo); +} + +/** + * poison_channel - poison buffers of a channel + * @iface: pointer to the interface the channel to be poisoned belongs to + * @channel_id: corresponding channel ID + * + * Destroy a channel and complete all the buffers in both started_list & + * pending_list. Return 0 on success, negative on failure. + */ +static int poison_channel(struct most_interface *most_iface, int ch_idx) +{ + struct dim2_hdm *dev = iface_to_hdm(most_iface); + struct hdm_channel *hdm_ch = dev->hch + ch_idx; + unsigned long flags; + u8 hal_ret; + int ret = 0; + + BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS); + + if (!hdm_ch->is_initialized) + return -EPERM; + + spin_lock_irqsave(&dim_lock, flags); + hal_ret = DIM_DestroyChannel(&hdm_ch->ch); + hdm_ch->is_initialized = false; + if (ch_idx == dev->atx_idx) + dev->atx_idx = -1; + spin_unlock_irqrestore(&dim_lock, flags); + if (hal_ret != DIM_NO_ERROR) { + pr_err("HAL Failed to close channel %s\n", hdm_ch->name); + ret = -EFAULT; + } + + complete_all_mbos(&hdm_ch->started_list); + complete_all_mbos(&hdm_ch->pending_list); + + return ret; +} + +/* + * dim2_probe - dim2 probe handler + * @pdev: platform device structure + * + * Register the dim2 interface with mostcore and initialize it. + * Return 0 on success, negative on failure. + */ +static int dim2_probe(struct platform_device *pdev) +{ + struct dim2_hdm *dev; + struct resource *res; + int ret, i; + struct kobject *kobj; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + dev->atx_idx = -1; + + platform_set_drvdata(pdev, dev); +#if defined(ENABLE_HDM_TEST) + test_dev = dev; +#else + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + pr_err("no memory region defined\n"); + ret = -ENOENT; + goto err_free_dev; + } + + if (!request_mem_region(res->start, resource_size(res), pdev->name)) { + pr_err("failed to request mem region\n"); + ret = -EBUSY; + goto err_free_dev; + } + + dev->io_base = ioremap(res->start, resource_size(res)); + if (!dev->io_base) { + pr_err("failed to ioremap\n"); + ret = -ENOMEM; + goto err_release_mem; + } + + ret = platform_get_irq(pdev, 0); + if (ret < 0) { + pr_err("failed to get irq\n"); + goto err_unmap_io; + } + dev->irq_ahb0 = ret; + + ret = request_irq(dev->irq_ahb0, dim2_ahb_isr, 0, "mlb_ahb0", dev); + if (ret) { + pr_err("failed to request IRQ: %d, err: %d\n", dev->irq_ahb0, ret); + goto err_unmap_io; + } +#endif + init_waitqueue_head(&dev->netinfo_waitq); + dev->deliver_netinfo = 0; + dev->netinfo_task = kthread_run(&deliver_netinfo_thread, (void *)dev, + "dim2_netinfo"); + if (IS_ERR(dev->netinfo_task)) { + ret = PTR_ERR(dev->netinfo_task); + goto err_free_irq; + } + + for (i = 0; i < DMA_CHANNELS; i++) { + struct most_channel_capability *cap = dev->capabilities + i; + struct hdm_channel *hdm_ch = dev->hch + i; + + INIT_LIST_HEAD(&hdm_ch->pending_list); + INIT_LIST_HEAD(&hdm_ch->started_list); + hdm_ch->is_initialized = false; + snprintf(hdm_ch->name, sizeof(hdm_ch->name), "ca%d", i * 2 + 2); + + cap->name_suffix = hdm_ch->name; + cap->direction = MOST_CH_RX | MOST_CH_TX; + cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC | + MOST_CH_ISOC_AVP | MOST_CH_SYNC; + cap->num_buffers_packet = MAX_BUFFERS_PACKET; + cap->buffer_size_packet = MAX_BUF_SIZE_PACKET; + cap->num_buffers_streaming = MAX_BUFFERS_STREAMING; + cap->buffer_size_streaming = MAX_BUF_SIZE_STREAMING; + } + + { + const char *fmt; + + if (sizeof(res->start) == sizeof(long long)) + fmt = "dim2-%016llx"; + else if (sizeof(res->start) == sizeof(long)) + fmt = "dim2-%016lx"; + else + fmt = "dim2-%016x"; + + snprintf(dev->name, sizeof(dev->name), fmt, res->start); + } + + dev->most_iface.interface = ITYPE_MEDIALB_DIM2; + dev->most_iface.description = dev->name; + dev->most_iface.num_channels = DMA_CHANNELS; + dev->most_iface.channel_vector = dev->capabilities; + dev->most_iface.configure = configure_channel; + dev->most_iface.enqueue = enqueue; + dev->most_iface.poison_channel = poison_channel; + dev->most_iface.request_netinfo = request_netinfo; + + kobj = most_register_interface(&dev->most_iface); + if (IS_ERR(kobj)) { + ret = PTR_ERR(kobj); + pr_err("failed to register MOST interface\n"); + goto err_stop_thread; + } + + ret = dim2_sysfs_probe(&dev->bus, kobj); + if (ret) + goto err_unreg_iface; + + ret = startup_dim(pdev); + if (ret) { + pr_err("failed to initialize DIM2\n"); + goto err_destroy_bus; + } + + return 0; + +err_destroy_bus: + dim2_sysfs_destroy(&dev->bus); +err_unreg_iface: + most_deregister_interface(&dev->most_iface); +err_stop_thread: + kthread_stop(dev->netinfo_task); +err_free_irq: +#if !defined(ENABLE_HDM_TEST) + free_irq(dev->irq_ahb0, dev); +err_unmap_io: + iounmap(dev->io_base); +err_release_mem: + release_mem_region(res->start, resource_size(res)); +err_free_dev: +#endif + kfree(dev); + + return ret; +} + +/** + * dim2_remove - dim2 remove handler + * @pdev: platform device structure + * + * Unregister the interface from mostcore + */ +static int dim2_remove(struct platform_device *pdev) +{ + struct dim2_hdm *dev = platform_get_drvdata(pdev); + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + struct dim2_platform_data *pdata = pdev->dev.platform_data; + unsigned long flags; + + spin_lock_irqsave(&dim_lock, flags); + DIM_Shutdown(); + spin_unlock_irqrestore(&dim_lock, flags); + + if (pdata && pdata->destroy) + pdata->destroy(pdata); + + dim2_sysfs_destroy(&dev->bus); + most_deregister_interface(&dev->most_iface); + kthread_stop(dev->netinfo_task); +#if !defined(ENABLE_HDM_TEST) + free_irq(dev->irq_ahb0, dev); + iounmap(dev->io_base); + release_mem_region(res->start, resource_size(res)); +#endif + kfree(dev); + platform_set_drvdata(pdev, NULL); + + /* + * break link to local platform_device_id struct + * to prevent crash by unload platform device module + */ + pdev->id_entry = 0; + + return 0; +} + +static struct platform_device_id dim2_id[] = { + { "medialb_dim2" }, + { }, /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(platform, dim2_id); + +static struct platform_driver dim2_driver = { + .probe = dim2_probe, + .remove = dim2_remove, + .id_table = dim2_id, + .driver = { + .name = "hdm_dim2", + .owner = THIS_MODULE, + }, +}; + +/** + * dim2_hdm_init - Driver Registration Routine + */ +static int __init dim2_hdm_init(void) +{ + pr_info("dim2_hdm_init()\n"); + return platform_driver_register(&dim2_driver); +} + +/** + * dim2_hdm_exit - Driver Cleanup Routine + **/ +static void __exit dim2_hdm_exit(void) +{ + pr_info("dim2_hdm_exit()\n"); + platform_driver_unregister(&dim2_driver); +} + +module_init(dim2_hdm_init); +module_exit(dim2_hdm_exit); + +MODULE_AUTHOR("Jain Roy Ambi <JainRoy.Ambi@microchip.com>"); +MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>"); +MODULE_DESCRIPTION("MediaLB DIM2 Hardware Dependent Module"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.h b/drivers/staging/most/hdm-dim2/dim2_hdm.h new file mode 100644 index 000000000000..6e6883232809 --- /dev/null +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.h @@ -0,0 +1,26 @@ +/* + * dim2_hdm.h - MediaLB DIM2 HDM Header + * + * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This file is licensed under GPLv2. + */ + +#ifndef DIM2_HDM_H +#define DIM2_HDM_H + +struct device; + +/* platform dependent data for dim2 interface */ +struct dim2_platform_data { + int (*init)(struct dim2_platform_data *pd, void *io_base, int clk_speed); + void (*destroy)(struct dim2_platform_data *pd); + void *priv; +}; + +#endif /* DIM2_HDM_H */ diff --git a/drivers/staging/most/hdm-dim2/dim2_reg.h b/drivers/staging/most/hdm-dim2/dim2_reg.h new file mode 100644 index 000000000000..476f66f4c566 --- /dev/null +++ b/drivers/staging/most/hdm-dim2/dim2_reg.h @@ -0,0 +1,176 @@ +/* + * dim2_reg.h - Definitions for registers of DIM2 + * (MediaLB, Device Interface Macro IP, OS62420) + * + * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This file is licensed under GPLv2. + */ + +#ifndef DIM2_OS62420_H +#define DIM2_OS62420_H + +#include <linux/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + + +struct dim2_regs { + /* 0x00 */ u32 MLBC0; + /* 0x01 */ u32 rsvd0[1]; + /* 0x02 */ u32 MLBPC0; + /* 0x03 */ u32 MS0; + /* 0x04 */ u32 rsvd1[1]; + /* 0x05 */ u32 MS1; + /* 0x06 */ u32 rsvd2[2]; + /* 0x08 */ u32 MSS; + /* 0x09 */ u32 MSD; + /* 0x0A */ u32 rsvd3[1]; + /* 0x0B */ u32 MIEN; + /* 0x0C */ u32 rsvd4[1]; + /* 0x0D */ u32 MLBPC2; + /* 0x0E */ u32 MLBPC1; + /* 0x0F */ u32 MLBC1; + /* 0x10 */ u32 rsvd5[0x10]; + /* 0x20 */ u32 HCTL; + /* 0x21 */ u32 rsvd6[1]; + /* 0x22 */ u32 HCMR0; + /* 0x23 */ u32 HCMR1; + /* 0x24 */ u32 HCER0; + /* 0x25 */ u32 HCER1; + /* 0x26 */ u32 HCBR0; + /* 0x27 */ u32 HCBR1; + /* 0x28 */ u32 rsvd7[8]; + /* 0x30 */ u32 MDAT0; + /* 0x31 */ u32 MDAT1; + /* 0x32 */ u32 MDAT2; + /* 0x33 */ u32 MDAT3; + /* 0x34 */ u32 MDWE0; + /* 0x35 */ u32 MDWE1; + /* 0x36 */ u32 MDWE2; + /* 0x37 */ u32 MDWE3; + /* 0x38 */ u32 MCTL; + /* 0x39 */ u32 MADR; + /* 0x3A */ u32 rsvd8[0xB6]; + /* 0xF0 */ u32 ACTL; + /* 0xF1 */ u32 rsvd9[3]; + /* 0xF4 */ u32 ACSR0; + /* 0xF5 */ u32 ACSR1; + /* 0xF6 */ u32 ACMR0; + /* 0xF7 */ u32 ACMR1; +}; + + +#define DIM2_MASK(n) (~((~(u32)0)<<(n))) + +enum { + MLBC0_MLBLK_BIT = 7, + + MLBC0_MLBPEN_BIT = 5, + + MLBC0_MLBCLK_SHIFT = 2, + MLBC0_MLBCLK_VAL_256FS = 0, + MLBC0_MLBCLK_VAL_512FS = 1, + MLBC0_MLBCLK_VAL_1024FS = 2, + MLBC0_MLBCLK_VAL_2048FS = 3, + + MLBC0_FCNT_SHIFT = 15, + MLBC0_FCNT_MASK = 7, + MLBC0_FCNT_VAL_1FPSB = 0, + MLBC0_FCNT_VAL_2FPSB = 1, + MLBC0_FCNT_VAL_4FPSB = 2, + MLBC0_FCNT_VAL_8FPSB = 3, + MLBC0_FCNT_VAL_16FPSB = 4, + MLBC0_FCNT_VAL_32FPSB = 5, + MLBC0_FCNT_VAL_64FPSB = 6, + + MLBC0_MLBEN_BIT = 0, + + MIEN_CTX_BREAK_BIT = 29, + MIEN_CTX_PE_BIT = 28, + MIEN_CTX_DONE_BIT = 27, + + MIEN_CRX_BREAK_BIT = 26, + MIEN_CRX_PE_BIT = 25, + MIEN_CRX_DONE_BIT = 24, + + MIEN_ATX_BREAK_BIT = 22, + MIEN_ATX_PE_BIT = 21, + MIEN_ATX_DONE_BIT = 20, + + MIEN_ARX_BREAK_BIT = 19, + MIEN_ARX_PE_BIT = 18, + MIEN_ARX_DONE_BIT = 17, + + MIEN_SYNC_PE_BIT = 16, + + MIEN_ISOC_BUFO_BIT = 1, + MIEN_ISOC_PE_BIT = 0, + + MLBC1_NDA_SHIFT = 8, + MLBC1_NDA_MASK = 0xFF, + + MLBC1_CLKMERR_BIT = 7, + MLBC1_LOCKERR_BIT = 6, + + ACTL_DMA_MODE_BIT = 2, + ACTL_DMA_MODE_VAL_DMA_MODE_0 = 0, + ACTL_DMA_MODE_VAL_DMA_MODE_1 = 1, + ACTL_SCE_BIT = 0, + + HCTL_EN_BIT = 15 +}; + +enum { + CDT1_BS_ISOC_SHIFT = 0, + CDT1_BS_ISOC_MASK = DIM2_MASK(9), + + CDT3_BD_SHIFT = 0, + CDT3_BD_MASK = DIM2_MASK(12), + CDT3_BD_ISOC_MASK = DIM2_MASK(13), + CDT3_BA_SHIFT = 16, + + ADT0_CE_BIT = 15, + ADT0_LE_BIT = 14, + ADT0_PG_BIT = 13, + + ADT1_RDY_BIT = 15, + ADT1_DNE_BIT = 14, + ADT1_ERR_BIT = 13, + ADT1_PS_BIT = 12, + ADT1_MEP_BIT = 11, + ADT1_BD_SHIFT = 0, + ADT1_CTRL_ASYNC_BD_MASK = DIM2_MASK(11), + ADT1_ISOC_SYNC_BD_MASK = DIM2_MASK(13), + + CAT_MFE_BIT = 14, + + CAT_MT_BIT = 13, + + CAT_RNW_BIT = 12, + + CAT_CE_BIT = 11, + + CAT_CT_SHIFT = 8, + CAT_CT_VAL_SYNC = 0, + CAT_CT_VAL_CONTROL = 1, + CAT_CT_VAL_ASYNC = 2, + CAT_CT_VAL_ISOC = 3, + + CAT_CL_SHIFT = 0, + CAT_CL_MASK = DIM2_MASK(6) +}; + + +#ifdef __cplusplus +} +#endif + +#endif /* DIM2_OS62420_H */ diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.c b/drivers/staging/most/hdm-dim2/dim2_sysfs.c new file mode 100644 index 000000000000..8e331a286fc3 --- /dev/null +++ b/drivers/staging/most/hdm-dim2/dim2_sysfs.c @@ -0,0 +1,116 @@ +/* + * dim2_sysfs.c - MediaLB sysfs information + * + * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This file is licensed under GPLv2. + */ + +/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/kernel.h> +#include "dim2_sysfs.h" + +struct bus_attr { + struct attribute attr; + ssize_t (*show)(struct medialb_bus *bus, char *buf); + ssize_t (*store)(struct medialb_bus *bus, const char *buf, size_t count); +}; + +static ssize_t state_show(struct medialb_bus *bus, char *buf) +{ + bool state = dim2_sysfs_get_state_cb(); + + return sprintf(buf, "%s\n", state ? "locked" : ""); +} + +static struct bus_attr state_attr = __ATTR_RO(state); + +static struct attribute *bus_default_attrs[] = { + &state_attr.attr, + NULL, +}; + +static struct attribute_group bus_attr_group = { + .attrs = bus_default_attrs, +}; + +static void bus_kobj_release(struct kobject *kobj) +{ +} + +static ssize_t bus_kobj_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct medialb_bus *bus = + container_of(kobj, struct medialb_bus, kobj_group); + struct bus_attr *xattr = container_of(attr, struct bus_attr, attr); + + if (!xattr->show) + return -EIO; + + return xattr->show(bus, buf); +} + +static ssize_t bus_kobj_attr_store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) +{ + ssize_t ret; + struct medialb_bus *bus = + container_of(kobj, struct medialb_bus, kobj_group); + struct bus_attr *xattr = container_of(attr, struct bus_attr, attr); + + if (!xattr->store) + return -EIO; + + ret = xattr->store(bus, buf, count); + return ret; +} + +static struct sysfs_ops const bus_kobj_sysfs_ops = { + .show = bus_kobj_attr_show, + .store = bus_kobj_attr_store, +}; + +static struct kobj_type bus_ktype = { + .release = bus_kobj_release, + .sysfs_ops = &bus_kobj_sysfs_ops, +}; + +int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj) +{ + int err; + + kobject_init(&bus->kobj_group, &bus_ktype); + err = kobject_add(&bus->kobj_group, parent_kobj, "bus"); + if (err) { + pr_err("kobject_add() failed: %d\n", err); + goto err_kobject_add; + } + + err = sysfs_create_group(&bus->kobj_group, &bus_attr_group); + if (err) { + pr_err("sysfs_create_group() failed: %d\n", err); + goto err_create_group; + } + + return 0; + +err_create_group: + kobject_put(&bus->kobj_group); + +err_kobject_add: + return err; +} + +void dim2_sysfs_destroy(struct medialb_bus *bus) +{ + kobject_put(&bus->kobj_group); +} diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.h b/drivers/staging/most/hdm-dim2/dim2_sysfs.h new file mode 100644 index 000000000000..e719691035b0 --- /dev/null +++ b/drivers/staging/most/hdm-dim2/dim2_sysfs.h @@ -0,0 +1,39 @@ +/* + * dim2_sysfs.h - MediaLB sysfs information + * + * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This file is licensed under GPLv2. + */ + +/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */ + +#ifndef DIM2_SYSFS_H +#define DIM2_SYSFS_H + + +#include <linux/kobject.h> + + +struct medialb_bus { + struct kobject kobj_group; +}; + +struct dim2_hdm; + +int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj); +void dim2_sysfs_destroy(struct medialb_bus *bus); + +/* + * callback, + * must deliver MediaLB state as true if locked or false if unlocked + */ +bool dim2_sysfs_get_state_cb(void); + + +#endif /* DIM2_SYSFS_H */ diff --git a/drivers/staging/most/hdm-i2c/Kconfig b/drivers/staging/most/hdm-i2c/Kconfig new file mode 100644 index 000000000000..6fd7983668ad --- /dev/null +++ b/drivers/staging/most/hdm-i2c/Kconfig @@ -0,0 +1,12 @@ +# +# MOST I2C configuration +# + +config HDM_I2C + tristate "I2C HDM" + depends on I2C + ---help--- + Say Y here if you want to connect via I2C to network tranceiver. + + To compile this driver as a module, choose M here: the + module will be called hdm_i2c. diff --git a/drivers/staging/most/hdm-i2c/Makefile b/drivers/staging/most/hdm-i2c/Makefile new file mode 100644 index 000000000000..03a4a59b1f9f --- /dev/null +++ b/drivers/staging/most/hdm-i2c/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_HDM_I2C) += hdm_i2c.o + +ccflags-y += -Idrivers/staging/most/mostcore/ diff --git a/drivers/staging/most/hdm-i2c/hdm_i2c.c b/drivers/staging/most/hdm-i2c/hdm_i2c.c new file mode 100644 index 000000000000..029ded3f250b --- /dev/null +++ b/drivers/staging/most/hdm-i2c/hdm_i2c.c @@ -0,0 +1,451 @@ +/* + * hdm_i2c.c - Hardware Dependent Module for I2C Interface + * + * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This file is licensed under GPLv2. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/err.h> + +#include <mostcore.h> + +enum { CH_RX, CH_TX, NUM_CHANNELS }; + +#define MAX_BUFFERS_CONTROL 32 +#define MAX_BUF_SIZE_CONTROL 256 + +/** + * list_first_mbo - get the first mbo from a list + * @ptr: the list head to take the mbo from. + */ +#define list_first_mbo(ptr) \ + list_first_entry(ptr, struct mbo, list) + + +/* IRQ / Polling option */ +static bool polling_req; +module_param(polling_req, bool, S_IRUGO); +MODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)"); + +/* Polling Rate */ +static int scan_rate = 100; +module_param(scan_rate, int, 0644); +MODULE_PARM_DESC(scan_rate, "Polling rate in times/sec. Default = 100"); + +struct hdm_i2c { + bool is_open[NUM_CHANNELS]; + bool polling_mode; + struct most_interface most_iface; + struct most_channel_capability capabilities[NUM_CHANNELS]; + struct i2c_client *client; + struct rx { + struct delayed_work dwork; + wait_queue_head_t waitq; + struct list_head list; + struct mutex list_mutex; + } rx; + char name[64]; +}; + +#define to_hdm(iface) container_of(iface, struct hdm_i2c, most_iface) + +/** + * configure_channel - called from MOST core to configure a channel + * @iface: interface the channel belongs to + * @channel: channel to be configured + * @channel_config: structure that holds the configuration information + * + * Return 0 on success, negative on failure. + * + * Receives configuration information from MOST core and initialize the + * corresponding channel. + */ +static int configure_channel(struct most_interface *most_iface, + int ch_idx, + struct most_channel_config *channel_config) +{ + struct hdm_i2c *dev = to_hdm(most_iface); + + BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS); + BUG_ON(dev->is_open[ch_idx]); + + if (channel_config->data_type != MOST_CH_CONTROL) { + pr_err("bad data type for channel %d\n", ch_idx); + return -EPERM; + } + + if (channel_config->direction != dev->capabilities[ch_idx].direction) { + pr_err("bad direction for channel %d\n", ch_idx); + return -EPERM; + } + + if (channel_config->direction == MOST_CH_RX) { + if (dev->polling_mode) + schedule_delayed_work(&dev->rx.dwork, + msecs_to_jiffies(MSEC_PER_SEC / 4)); + } + dev->is_open[ch_idx] = true; + + return 0; +} + +/** + * enqueue - called from MOST core to enqueue a buffer for data transfer + * @iface: intended interface + * @channel: ID of the channel the buffer is intended for + * @mbo: pointer to the buffer object + * + * Return 0 on success, negative on failure. + * + * Transmit the data over I2C if it is a "write" request or push the buffer into + * list if it is an "read" request + */ +static int enqueue(struct most_interface *most_iface, + int ch_idx, struct mbo *mbo) +{ + struct hdm_i2c *dev = to_hdm(most_iface); + int ret; + + BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS); + BUG_ON(!dev->is_open[ch_idx]); + + if (ch_idx == CH_RX) { + /* RX */ + mutex_lock(&dev->rx.list_mutex); + list_add_tail(&mbo->list, &dev->rx.list); + mutex_unlock(&dev->rx.list_mutex); + wake_up_interruptible(&dev->rx.waitq); + } else { + /* TX */ + ret = i2c_master_send(dev->client, mbo->virt_address, + mbo->buffer_length); + if (ret <= 0) { + mbo->processed_length = 0; + mbo->status = MBO_E_INVAL; + } else { + mbo->processed_length = mbo->buffer_length; + mbo->status = MBO_SUCCESS; + } + mbo->complete(mbo); + } + + return 0; +} + +/** + * poison_channel - called from MOST core to poison buffers of a channel + * @iface: pointer to the interface the channel to be poisoned belongs to + * @channel_id: corresponding channel ID + * + * Return 0 on success, negative on failure. + * + * If channel direction is RX, complete the buffers in list with + * status MBO_E_CLOSE + */ +static int poison_channel(struct most_interface *most_iface, + int ch_idx) +{ + struct hdm_i2c *dev = to_hdm(most_iface); + struct mbo *mbo; + + BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS); + BUG_ON(!dev->is_open[ch_idx]); + + dev->is_open[ch_idx] = false; + + if (ch_idx == CH_RX) { + mutex_lock(&dev->rx.list_mutex); + while (!list_empty(&dev->rx.list)) { + mbo = list_first_mbo(&dev->rx.list); + list_del(&mbo->list); + mutex_unlock(&dev->rx.list_mutex); + + mbo->processed_length = 0; + mbo->status = MBO_E_CLOSE; + mbo->complete(mbo); + + mutex_lock(&dev->rx.list_mutex); + } + mutex_unlock(&dev->rx.list_mutex); + wake_up_interruptible(&dev->rx.waitq); + } + + return 0; +} + +static void request_netinfo(struct most_interface *most_iface, + int ch_idx) +{ + pr_info("request_netinfo()\n"); +} + +static void do_rx_work(struct hdm_i2c *dev) +{ + struct mbo *mbo; + unsigned char msg[MAX_BUF_SIZE_CONTROL]; + int ret, ch_idx = CH_RX; + uint16_t pml, data_size; + + /* Read PML (2 bytes) */ + ret = i2c_master_recv(dev->client, msg, 2); + if (ret <= 0) { + pr_err("Failed to receive PML\n"); + return; + } + + pml = (msg[0] << 8) | msg[1]; + if (!pml) + return; + + data_size = pml + 2; + + /* Read the whole message, including PML */ + ret = i2c_master_recv(dev->client, msg, data_size); + if (ret <= 0) { + pr_err("Failed to receive a Port Message\n"); + return; + } + + for (;;) { + /* Conditions to wait for: poisoned channel or free buffer + available for reading */ + if (wait_event_interruptible(dev->rx.waitq, + !dev->is_open[ch_idx] || + !list_empty(&dev->rx.list))) { + pr_err("wait_event_interruptible() failed\n"); + return; + } + + if (!dev->is_open[ch_idx]) + return; + + mutex_lock(&dev->rx.list_mutex); + + /* list may be empty if poison or remove is called */ + if (!list_empty(&dev->rx.list)) + break; + + mutex_unlock(&dev->rx.list_mutex); + } + + mbo = list_first_mbo(&dev->rx.list); + list_del(&mbo->list); + mutex_unlock(&dev->rx.list_mutex); + + mbo->processed_length = min(data_size, mbo->buffer_length); + memcpy(mbo->virt_address, msg, mbo->processed_length); + mbo->status = MBO_SUCCESS; + mbo->complete(mbo); +} + +/** + * pending_rx_work - Read pending messages through I2C + * @work: definition of this work item + * + * Invoked by the Interrupt Service Routine, most_irq_handler() + */ +static void pending_rx_work(struct work_struct *work) +{ + struct hdm_i2c *dev = container_of(work, struct hdm_i2c, rx.dwork.work); + + do_rx_work(dev); + + if (dev->polling_mode) { + if (dev->is_open[CH_RX]) + schedule_delayed_work(&dev->rx.dwork, + msecs_to_jiffies(MSEC_PER_SEC + / scan_rate)); + } else + enable_irq(dev->client->irq); +} + +/* + * most_irq_handler - Interrupt Service Routine + * @irq: irq number + * @_dev: private data + * + * Schedules a delayed work + * + * By default the interrupt line behavior is Active Low. Once an interrupt is + * generated by the device, until driver clears the interrupt (by reading + * the PMP message), device keeps the interrupt line in low state. Since i2c + * read is done in work queue, the interrupt line must be disabled temporarily + * to avoid ISR being called repeatedly. Re-enable the interrupt in workqueue, + * after reading the message. + * + * Note: If we use the interrupt line in Falling edge mode, there is a + * possibility to miss interrupts when ISR is getting executed. + * + */ +static irqreturn_t most_irq_handler(int irq, void *_dev) +{ + struct hdm_i2c *dev = _dev; + + disable_irq_nosync(irq); + + schedule_delayed_work(&dev->rx.dwork, 0); + + return IRQ_HANDLED; +} + +/* + * i2c_probe - i2c probe handler + * @client: i2c client device structure + * @id: i2c client device id + * + * Return 0 on success, negative on failure. + * + * Register the i2c client device as a MOST interface + */ +static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct hdm_i2c *dev; + int ret, i; + struct kobject *kobj; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + /* ID format: i2c-<bus>-<address> */ + snprintf(dev->name, sizeof(dev->name), "i2c-%d-%04x", + client->adapter->nr, client->addr); + + for (i = 0; i < NUM_CHANNELS; i++) { + dev->is_open[i] = false; + dev->capabilities[i].data_type = MOST_CH_CONTROL; + dev->capabilities[i].num_buffers_packet = MAX_BUFFERS_CONTROL; + dev->capabilities[i].buffer_size_packet = MAX_BUF_SIZE_CONTROL; + } + dev->capabilities[CH_RX].direction = MOST_CH_RX; + dev->capabilities[CH_RX].name_suffix = "rx"; + dev->capabilities[CH_TX].direction = MOST_CH_TX; + dev->capabilities[CH_TX].name_suffix = "tx"; + + dev->most_iface.interface = ITYPE_I2C; + dev->most_iface.description = dev->name; + dev->most_iface.num_channels = NUM_CHANNELS; + dev->most_iface.channel_vector = dev->capabilities; + dev->most_iface.configure = configure_channel; + dev->most_iface.enqueue = enqueue; + dev->most_iface.poison_channel = poison_channel; + dev->most_iface.request_netinfo = request_netinfo; + + INIT_LIST_HEAD(&dev->rx.list); + mutex_init(&dev->rx.list_mutex); + init_waitqueue_head(&dev->rx.waitq); + + INIT_DELAYED_WORK(&dev->rx.dwork, pending_rx_work); + + dev->client = client; + i2c_set_clientdata(client, dev); + + kobj = most_register_interface(&dev->most_iface); + if (IS_ERR(kobj)) { + pr_err("Failed to register i2c as a MOST interface\n"); + kfree(dev); + return PTR_ERR(kobj); + } + + dev->polling_mode = polling_req || client->irq <= 0; + if (!dev->polling_mode) { + pr_info("Requesting IRQ: %d\n", client->irq); + ret = request_irq(client->irq, most_irq_handler, IRQF_SHARED, + client->name, dev); + if (ret) { + pr_info("IRQ request failed: %d, " + "falling back to polling\n", ret); + dev->polling_mode = true; + } + } + + if (dev->polling_mode) + pr_info("Using polling at rate: %d times/sec\n", scan_rate); + + return 0; +} + +/* + * i2c_remove - i2c remove handler + * @client: i2c client device structure + * + * Return 0 on success. + * + * Unregister the i2c client device as a MOST interface + */ +static int i2c_remove(struct i2c_client *client) +{ + struct hdm_i2c *dev = i2c_get_clientdata(client); + int i; + + if (!dev->polling_mode) + free_irq(client->irq, dev); + + most_deregister_interface(&dev->most_iface); + + for (i = 0 ; i < NUM_CHANNELS; i++) + if (dev->is_open[i]) + poison_channel(&dev->most_iface, i); + cancel_delayed_work_sync(&dev->rx.dwork); + kfree(dev); + + return 0; +} + +static const struct i2c_device_id i2c_id[] = { + { "most_i2c", 0 }, + { }, /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(i2c, i2c_id); + +static struct i2c_driver i2c_driver = { + .driver = { + .name = "hdm_i2c", + .owner = THIS_MODULE, + }, + .probe = i2c_probe, + .remove = i2c_remove, + .id_table = i2c_id, +}; + +/** + * hdm_i2c_init - Driver Registration Routine + */ +static int __init hdm_i2c_init(void) +{ + pr_info("hdm_i2c_init()\n"); + + return i2c_add_driver(&i2c_driver); +} + +/** + * hdm_i2c_exit - Driver Cleanup Routine + **/ +static void __exit hdm_i2c_exit(void) +{ + i2c_del_driver(&i2c_driver); + pr_info("hdm_i2c_exit()\n"); +} + +module_init(hdm_i2c_init); +module_exit(hdm_i2c_exit); + +MODULE_AUTHOR("Jain Roy Ambi <JainRoy.Ambi@microchip.com>"); +MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>"); +MODULE_DESCRIPTION("I2C Hardware Dependent Module"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/most/hdm-usb/Kconfig b/drivers/staging/most/hdm-usb/Kconfig new file mode 100644 index 000000000000..a482c3fdf34b --- /dev/null +++ b/drivers/staging/most/hdm-usb/Kconfig @@ -0,0 +1,14 @@ +# +# MOST USB configuration +# + +config HDM_USB + tristate "USB HDM" + depends on USB + select AIM_NETWORK + ---help--- + Say Y here if you want to connect via USB to network tranceiver. + This device driver depends on the networking AIM. + + To compile this driver as a module, choose M here: the + module will be called hdm_usb. diff --git a/drivers/staging/most/hdm-usb/Makefile b/drivers/staging/most/hdm-usb/Makefile new file mode 100644 index 000000000000..6bbacb41e94b --- /dev/null +++ b/drivers/staging/most/hdm-usb/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_HDM_USB) += hdm_usb.o + +ccflags-y += -Idrivers/staging/most/mostcore/ +ccflags-y += -Idrivers/staging/most/aim-network/ diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c new file mode 100644 index 000000000000..514ce3529b7a --- /dev/null +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -0,0 +1,1454 @@ +/* + * hdm_usb.c - Hardware dependent module for USB + * + * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This file is licensed under GPLv2. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/module.h> +#include <linux/fs.h> +#include <linux/usb.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/cdev.h> +#include <linux/device.h> +#include <linux/list.h> +#include <linux/completion.h> +#include <linux/mutex.h> +#include <linux/spinlock.h> +#include <linux/interrupt.h> +#include <linux/workqueue.h> +#include <linux/sysfs.h> +#include <linux/dma-mapping.h> +#include <linux/etherdevice.h> +#include <linux/uaccess.h> +#include "mostcore.h" +#include "networking.h" + +#define USB_MTU 512 +#define NO_ISOCHRONOUS_URB 0 +#define AV_PACKETS_PER_XACT 2 +#define BUF_CHAIN_SIZE 0xFFFF +#define MAX_NUM_ENDPOINTS 30 +#define MAX_SUFFIX_LEN 10 +#define MAX_STRING_LEN 80 +#define MAX_BUF_SIZE 0xFFFF +#define CEILING(x, y) (((x) + (y) - 1) / (y)) + +#define USB_VENDOR_ID_SMSC 0x0424 /* VID: SMSC */ +#define USB_DEV_ID_BRDG 0xC001 /* PID: USB Bridge */ +#define USB_DEV_ID_INIC 0xCF18 /* PID: USB INIC */ +#define HW_RESYNC 0x0000 +/* DRCI Addresses */ +#define DRCI_REG_NI_STATE 0x0100 +#define DRCI_REG_PACKET_BW 0x0101 +#define DRCI_REG_NODE_ADDR 0x0102 +#define DRCI_REG_NODE_POS 0x0103 +#define DRCI_REG_MEP_FILTER 0x0140 +#define DRCI_REG_HASH_TBL0 0x0141 +#define DRCI_REG_HASH_TBL1 0x0142 +#define DRCI_REG_HASH_TBL2 0x0143 +#define DRCI_REG_HASH_TBL3 0x0144 +#define DRCI_REG_HW_ADDR_HI 0x0145 +#define DRCI_REG_HW_ADDR_MI 0x0146 +#define DRCI_REG_HW_ADDR_LO 0x0147 +#define DRCI_READ_REQ 0xA0 +#define DRCI_WRITE_REQ 0xA1 + +/** + * struct buf_anchor - used to create a list of pending URBs + * @urb: pointer to USB request block + * @clear_work_obj: + * @list: linked list + * @urb_completion: + */ +struct buf_anchor { + struct urb *urb; + struct work_struct clear_work_obj; + struct list_head list; + struct completion urb_compl; +}; +#define to_buf_anchor(w) container_of(w, struct buf_anchor, clear_work_obj) + +/** + * struct most_dci_obj - Direct Communication Interface + * @kobj:position in sysfs + * @usb_device: pointer to the usb device + */ +struct most_dci_obj { + struct kobject kobj; + struct usb_device *usb_device; +}; +#define to_dci_obj(p) container_of(p, struct most_dci_obj, kobj) + +/** + * struct most_dev - holds all usb interface specific stuff + * @parent: parent object in sysfs + * @usb_device: pointer to usb device + * @iface: hardware interface + * @cap: channel capabilities + * @conf: channel configuration + * @dci: direct communication interface of hardware + * @hw_addr: MAC address of hardware + * @ep_address: endpoint address table + * @link_stat: link status of hardware + * @description: device description + * @suffix: suffix for channel name + * @anchor_list_lock: locks list access + * @padding_active: indicates channel uses padding + * @is_channel_healthy: health status table of each channel + * @anchor_list: list of anchored items + * @io_mutex: synchronize I/O with disconnect + * @link_stat_timer: timer for link status reports + * @poll_work_obj: work for polling link status + */ +struct most_dev { + struct kobject *parent; + struct usb_device *usb_device; + struct most_interface iface; + struct most_channel_capability *cap; + struct most_channel_config *conf; + struct most_dci_obj *dci; + u8 hw_addr[6]; + u8 *ep_address; + u16 link_stat; + char description[MAX_STRING_LEN]; + char suffix[MAX_NUM_ENDPOINTS][MAX_SUFFIX_LEN]; + spinlock_t anchor_list_lock[MAX_NUM_ENDPOINTS]; + bool padding_active[MAX_NUM_ENDPOINTS]; + bool is_channel_healthy[MAX_NUM_ENDPOINTS]; + struct list_head *anchor_list; + struct mutex io_mutex; + struct timer_list link_stat_timer; + struct work_struct poll_work_obj; +}; +#define to_mdev(d) container_of(d, struct most_dev, iface) +#define to_mdev_from_work(w) container_of(w, struct most_dev, poll_work_obj) + +static struct workqueue_struct *schedule_usb_work; +static void wq_clear_halt(struct work_struct *wq_obj); +static void wq_netinfo(struct work_struct *wq_obj); + +/** + * trigger_resync_vr - Vendor request to trigger HW re-sync mechanism + * @dev: usb device + * + */ +static void trigger_resync_vr(struct usb_device *dev) +{ + int retval; + u8 request_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; + int *data = kzalloc(sizeof(*data), GFP_KERNEL); + + if (!data) + goto error; + *data = HW_RESYNC; + retval = usb_control_msg(dev, + usb_sndctrlpipe(dev, 0), + 0, + request_type, + 0, + 0, + data, + 0, + 5 * HZ); + kfree(data); + if (retval >= 0) + return; +error: + dev_err(&dev->dev, "Vendor request \"stall\" failed\n"); +} + +/** + * drci_rd_reg - read a DCI register + * @dev: usb device + * @reg: register address + * @buf: buffer to store data + * + * This is reads data from INIC's direct register communication interface + */ +static inline int drci_rd_reg(struct usb_device *dev, u16 reg, void *buf) +{ + return usb_control_msg(dev, + usb_rcvctrlpipe(dev, 0), + DRCI_READ_REQ, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x0000, + reg, + buf, + 2, + 5 * HZ); +} + +/** + * drci_wr_reg - write a DCI register + * @dev: usb device + * @reg: register address + * @data: data to write + * + * This is writes data to INIC's direct register communication interface + */ +static inline int drci_wr_reg(struct usb_device *dev, u16 reg, u16 data) +{ + return usb_control_msg(dev, + usb_sndctrlpipe(dev, 0), + DRCI_WRITE_REQ, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + data, + reg, + NULL, + 0, + 5 * HZ); +} + +/** + * free_anchored_buffers - free device's anchored items + * @mdev: the device + * @channel: channel ID + */ +static void free_anchored_buffers(struct most_dev *mdev, unsigned int channel) +{ + struct mbo *mbo; + struct buf_anchor *anchor, *tmp; + unsigned long flags; + + spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); + list_for_each_entry_safe(anchor, tmp, &mdev->anchor_list[channel], list) { + struct urb *urb = anchor->urb; + + spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); + if (likely(urb)) { + mbo = urb->context; + if (!irqs_disabled()) { + usb_kill_urb(urb); + } else { + usb_unlink_urb(urb); + wait_for_completion(&anchor->urb_compl); + } + if ((mbo) && (mbo->complete)) { + mbo->status = MBO_E_CLOSE; + mbo->processed_length = 0; + mbo->complete(mbo); + } + usb_free_urb(urb); + } + spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); + list_del(&anchor->list); + kfree(anchor); + } + spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); +} + +/** + * get_stream_frame_size - calculate frame size of current configuration + * @cfg: channel configuration + */ +static unsigned int get_stream_frame_size(struct most_channel_config *cfg) +{ + unsigned int frame_size = 0; + unsigned int sub_size = cfg->subbuffer_size; + + if (!sub_size) { + pr_warn("Misconfig: Subbuffer size zero.\n"); + return frame_size; + } + switch (cfg->data_type) { + case MOST_CH_ISOC_AVP: + frame_size = AV_PACKETS_PER_XACT * sub_size; + break; + case MOST_CH_SYNC: + if (cfg->packets_per_xact == 0) { + pr_warn("Misconfig: Packets per XACT zero\n"); + frame_size = 0; + } else if (cfg->packets_per_xact == 0xFF) + frame_size = (USB_MTU / sub_size) * sub_size; + else + frame_size = cfg->packets_per_xact * sub_size; + break; + default: + pr_warn("Query frame size of non-streaming channel\n"); + break; + } + return frame_size; +} + +/** + * hdm_poison_channel - mark buffers of this channel as invalid + * @iface: pointer to the interface + * @channel: channel ID + * + * This unlinks all URBs submitted to the HCD, + * calls the associated completion function of the core and removes + * them from the list. + * + * Returns 0 on success or error code otherwise. + */ +int hdm_poison_channel(struct most_interface *iface, int channel) +{ + struct most_dev *mdev; + + mdev = to_mdev(iface); + if (unlikely(!iface)) { + dev_warn(&mdev->usb_device->dev, "Poison: Bad interface.\n"); + return -EIO; + } + if (unlikely((channel < 0) || (channel >= iface->num_channels))) { + dev_warn(&mdev->usb_device->dev, "Channel ID out of range.\n"); + return -ECHRNG; + } + + mdev->is_channel_healthy[channel] = false; + + mutex_lock(&mdev->io_mutex); + free_anchored_buffers(mdev, channel); + if (mdev->padding_active[channel] == true) + mdev->padding_active[channel] = false; + + if (mdev->conf[channel].data_type == MOST_CH_ASYNC) { + del_timer_sync(&mdev->link_stat_timer); + cancel_work_sync(&mdev->poll_work_obj); + } + mutex_unlock(&mdev->io_mutex); + return 0; +} + +/** + * hdm_add_padding - add padding bytes + * @mdev: most device + * @channel: channel ID + * @mbo: buffer object + * + * This inserts the INIC hardware specific padding bytes into a streaming + * channel's buffer + */ +int hdm_add_padding(struct most_dev *mdev, int channel, struct mbo *mbo) +{ + struct most_channel_config *conf = &mdev->conf[channel]; + unsigned int j, num_frames, frame_size; + u16 rd_addr, wr_addr; + + frame_size = get_stream_frame_size(conf); + if (!frame_size) + return -EIO; + num_frames = mbo->buffer_length / frame_size; + + if (num_frames < 1) { + dev_err(&mdev->usb_device->dev, + "Missed minimal transfer unit.\n"); + return -EIO; + } + + for (j = 1; j < num_frames; j++) { + wr_addr = (num_frames - j) * USB_MTU; + rd_addr = (num_frames - j) * frame_size; + memmove(mbo->virt_address + wr_addr, + mbo->virt_address + rd_addr, + frame_size); + } + mbo->buffer_length = num_frames * USB_MTU; + return 0; +} + +/** + * hdm_remove_padding - remove padding bytes + * @mdev: most device + * @channel: channel ID + * @mbo: buffer object + * + * This takes the INIC hardware specific padding bytes off a streaming + * channel's buffer. + */ +int hdm_remove_padding(struct most_dev *mdev, int channel, struct mbo *mbo) +{ + unsigned int j, num_frames, frame_size; + struct most_channel_config *const conf = &mdev->conf[channel]; + + frame_size = get_stream_frame_size(conf); + if (!frame_size) + return -EIO; + num_frames = mbo->processed_length / USB_MTU; + + for (j = 1; j < num_frames; j++) + memmove(mbo->virt_address + frame_size * j, + mbo->virt_address + USB_MTU * j, + frame_size); + + mbo->processed_length = frame_size * num_frames; + return 0; +} + +/** + * hdm_write_completion - completion function for submitted Tx URBs + * @urb: the URB that has been completed + * + * This checks the status of the completed URB. In case the URB has been + * unlinked before, it is immediately freed. On any other error the MBO + * transfer flag is set. On success it frees allocated resources and calls + * the completion function. + * + * Context: interrupt! + */ +static void hdm_write_completion(struct urb *urb) +{ + struct mbo *mbo; + struct buf_anchor *anchor; + struct most_dev *mdev; + struct device *dev; + unsigned int channel; + unsigned long flags; + + mbo = urb->context; + anchor = mbo->priv; + mdev = to_mdev(mbo->ifp); + channel = mbo->hdm_channel_id; + dev = &mdev->usb_device->dev; + + if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET) || + (mdev->is_channel_healthy[channel] == false)) { + complete(&anchor->urb_compl); + return; + } + + if (unlikely(urb->status && !(urb->status == -ENOENT || + urb->status == -ECONNRESET || + urb->status == -ESHUTDOWN))) { + mbo->processed_length = 0; + switch (urb->status) { + case -EPIPE: + dev_warn(dev, "Broken OUT pipe detected\n"); + most_stop_enqueue(&mdev->iface, channel); + mbo->status = MBO_E_INVAL; + usb_unlink_urb(urb); + INIT_WORK(&anchor->clear_work_obj, wq_clear_halt); + queue_work(schedule_usb_work, &anchor->clear_work_obj); + return; + case -ENODEV: + case -EPROTO: + mbo->status = MBO_E_CLOSE; + break; + default: + mbo->status = MBO_E_INVAL; + break; + } + } else { + mbo->status = MBO_SUCCESS; + mbo->processed_length = urb->actual_length; + } + + spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); + list_del(&anchor->list); + spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); + kfree(anchor); + + if (likely(mbo->complete)) + mbo->complete(mbo); + usb_free_urb(urb); +} + +/** + * hdm_read_completion - completion funciton for submitted Rx URBs + * @urb: the URB that has been completed + * + * This checks the status of the completed URB. In case the URB has been + * unlinked before it is immediately freed. On any other error the MBO transfer + * flag is set. On success it frees allocated resources, removes + * padding bytes -if necessary- and calls the completion function. + * + * Context: interrupt! + * + * ************************************************************************** + * Error codes returned by in urb->status + * or in iso_frame_desc[n].status (for ISO) + * ************************************************************************* + * + * USB device drivers may only test urb status values in completion handlers. + * This is because otherwise there would be a race between HCDs updating + * these values on one CPU, and device drivers testing them on another CPU. + * + * A transfer's actual_length may be positive even when an error has been + * reported. That's because transfers often involve several packets, so that + * one or more packets could finish before an error stops further endpoint I/O. + * + * For isochronous URBs, the urb status value is non-zero only if the URB is + * unlinked, the device is removed, the host controller is disabled or the total + * transferred length is less than the requested length and the URB_SHORT_NOT_OK + * flag is set. Completion handlers for isochronous URBs should only see + * urb->status set to zero, -ENOENT, -ECONNRESET, -ESHUTDOWN, or -EREMOTEIO. + * Individual frame descriptor status fields may report more status codes. + * + * + * 0 Transfer completed successfully + * + * -ENOENT URB was synchronously unlinked by usb_unlink_urb + * + * -EINPROGRESS URB still pending, no results yet + * (That is, if drivers see this it's a bug.) + * + * -EPROTO (*, **) a) bitstuff error + * b) no response packet received within the + * prescribed bus turn-around time + * c) unknown USB error + * + * -EILSEQ (*, **) a) CRC mismatch + * b) no response packet received within the + * prescribed bus turn-around time + * c) unknown USB error + * + * Note that often the controller hardware does not + * distinguish among cases a), b), and c), so a + * driver cannot tell whether there was a protocol + * error, a failure to respond (often caused by + * device disconnect), or some other fault. + * + * -ETIME (**) No response packet received within the prescribed + * bus turn-around time. This error may instead be + * reported as -EPROTO or -EILSEQ. + * + * -ETIMEDOUT Synchronous USB message functions use this code + * to indicate timeout expired before the transfer + * completed, and no other error was reported by HC. + * + * -EPIPE (**) Endpoint stalled. For non-control endpoints, + * reset this status with usb_clear_halt(). + * + * -ECOMM During an IN transfer, the host controller + * received data from an endpoint faster than it + * could be written to system memory + * + * -ENOSR During an OUT transfer, the host controller + * could not retrieve data from system memory fast + * enough to keep up with the USB data rate + * + * -EOVERFLOW (*) The amount of data returned by the endpoint was + * greater than either the max packet size of the + * endpoint or the remaining buffer size. "Babble". + * + * -EREMOTEIO The data read from the endpoint did not fill the + * specified buffer, and URB_SHORT_NOT_OK was set in + * urb->transfer_flags. + * + * -ENODEV Device was removed. Often preceded by a burst of + * other errors, since the hub driver doesn't detect + * device removal events immediately. + * + * -EXDEV ISO transfer only partially completed + * (only set in iso_frame_desc[n].status, not urb->status) + * + * -EINVAL ISO madness, if this happens: Log off and go home + * + * -ECONNRESET URB was asynchronously unlinked by usb_unlink_urb + * + * -ESHUTDOWN The device or host controller has been disabled due + * to some problem that could not be worked around, + * such as a physical disconnect. + * + * + * (*) Error codes like -EPROTO, -EILSEQ and -EOVERFLOW normally indicate + * hardware problems such as bad devices (including firmware) or cables. + * + * (**) This is also one of several codes that different kinds of host + * controller use to indicate a transfer has failed because of device + * disconnect. In the interval before the hub driver starts disconnect + * processing, devices may receive such fault reports for every request. + * + * See <https://www.kernel.org/doc/Documentation/usb/error-codes.txt> + */ +static void hdm_read_completion(struct urb *urb) +{ + struct mbo *mbo; + struct buf_anchor *anchor; + struct most_dev *mdev; + struct device *dev; + unsigned long flags; + unsigned int channel; + struct most_channel_config *conf; + + mbo = urb->context; + anchor = mbo->priv; + mdev = to_mdev(mbo->ifp); + channel = mbo->hdm_channel_id; + dev = &mdev->usb_device->dev; + + if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET) || + (mdev->is_channel_healthy[channel] == false)) { + complete(&anchor->urb_compl); + return; + } + + conf = &mdev->conf[channel]; + + if (unlikely(urb->status && !(urb->status == -ENOENT || + urb->status == -ECONNRESET || + urb->status == -ESHUTDOWN))) { + mbo->processed_length = 0; + switch (urb->status) { + case -EPIPE: + dev_warn(dev, "Broken IN pipe detected\n"); + mbo->status = MBO_E_INVAL; + usb_unlink_urb(urb); + INIT_WORK(&anchor->clear_work_obj, wq_clear_halt); + queue_work(schedule_usb_work, &anchor->clear_work_obj); + return; + case -ENODEV: + case -EPROTO: + mbo->status = MBO_E_CLOSE; + break; + case -EOVERFLOW: + dev_warn(dev, "Babble on IN pipe detected\n"); + default: + mbo->status = MBO_E_INVAL; + break; + } + } else { + mbo->processed_length = urb->actual_length; + if (mdev->padding_active[channel] == false) { + mbo->status = MBO_SUCCESS; + } else { + if (hdm_remove_padding(mdev, channel, mbo)) { + mbo->processed_length = 0; + mbo->status = MBO_E_INVAL; + } else { + mbo->status = MBO_SUCCESS; + } + } + } + spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); + list_del(&anchor->list); + spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); + kfree(anchor); + + if (likely(mbo->complete)) + mbo->complete(mbo); + usb_free_urb(urb); +} + +/** + * hdm_enqueue - receive a buffer to be used for data transfer + * @iface: interface to enqueue to + * @channel: ID of the channel + * @mbo: pointer to the buffer object + * + * This allocates a new URB and fills it according to the channel + * that is being used for transmission of data. Before the URB is + * submitted it is stored in the private anchor list. + * + * Returns 0 on success. On any error the URB is freed and a error code + * is returned. + * + * Context: Could in _some_ cases be interrupt! + */ +int hdm_enqueue(struct most_interface *iface, int channel, struct mbo *mbo) +{ + struct most_dev *mdev; + struct buf_anchor *anchor; + struct most_channel_config *conf; + struct device *dev; + int retval = 0; + struct urb *urb; + unsigned long flags; + unsigned long length; + void *virt_address; + + if (unlikely(!iface || !mbo)) + return -EIO; + if (unlikely(iface->num_channels <= channel) || (channel < 0)) + return -ECHRNG; + + mdev = to_mdev(iface); + conf = &mdev->conf[channel]; + dev = &mdev->usb_device->dev; + + if (!mdev->usb_device) + return -ENODEV; + + urb = usb_alloc_urb(NO_ISOCHRONOUS_URB, GFP_ATOMIC); + if (!urb) { + dev_err(dev, "Failed to allocate URB\n"); + return -ENOMEM; + } + + anchor = kzalloc(sizeof(*anchor), GFP_ATOMIC); + if (!anchor) { + retval = -ENOMEM; + goto _error; + } + + anchor->urb = urb; + init_completion(&anchor->urb_compl); + mbo->priv = anchor; + + spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); + list_add_tail(&anchor->list, &mdev->anchor_list[channel]); + spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); + + if ((mdev->padding_active[channel] == true) && + (conf->direction & MOST_CH_TX)) + if (hdm_add_padding(mdev, channel, mbo)) { + retval = -EIO; + goto _error_1; + } + + urb->transfer_dma = mbo->bus_address; + virt_address = mbo->virt_address; + length = mbo->buffer_length; + + if (conf->direction & MOST_CH_TX) { + usb_fill_bulk_urb(urb, mdev->usb_device, + usb_sndbulkpipe(mdev->usb_device, + mdev->ep_address[channel]), + virt_address, + length, + hdm_write_completion, + mbo); + if (conf->data_type != MOST_CH_ISOC_AVP) + urb->transfer_flags |= URB_ZERO_PACKET; + } else { + usb_fill_bulk_urb(urb, mdev->usb_device, + usb_rcvbulkpipe(mdev->usb_device, + mdev->ep_address[channel]), + virt_address, + length, + hdm_read_completion, + mbo); + } + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + retval = usb_submit_urb(urb, GFP_KERNEL); + if (retval) { + dev_err(dev, "URB submit failed with error %d.\n", retval); + goto _error_1; + } + return 0; + +_error_1: + spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); + list_del(&anchor->list); + spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); + kfree(anchor); +_error: + usb_free_urb(urb); + return retval; +} + +/** + * hdm_configure_channel - receive channel configuration from core + * @iface: interface + * @channel: channel ID + * @conf: structure that holds the configuration information + */ +int hdm_configure_channel(struct most_interface *iface, int channel, + struct most_channel_config *conf) +{ + unsigned int num_frames; + unsigned int frame_size; + unsigned int temp_size; + unsigned int tail_space; + struct most_dev *mdev; + struct device *dev; + + mdev = to_mdev(iface); + mdev->is_channel_healthy[channel] = true; + dev = &mdev->usb_device->dev; + + if (unlikely(!iface || !conf)) { + dev_err(dev, "Bad interface or config pointer.\n"); + return -EINVAL; + } + if (unlikely((channel < 0) || (channel >= iface->num_channels))) { + dev_err(dev, "Channel ID out of range.\n"); + return -EINVAL; + } + if ((!conf->num_buffers) || (!conf->buffer_size)) { + dev_err(dev, "Misconfig: buffer size or #buffers zero.\n"); + return -EINVAL; + } + + if (!(conf->data_type == MOST_CH_SYNC) && + !((conf->data_type == MOST_CH_ISOC_AVP) && + (conf->packets_per_xact != 0xFF))) { + mdev->padding_active[channel] = false; + goto exit; + } + + mdev->padding_active[channel] = true; + temp_size = conf->buffer_size; + + if ((conf->data_type != MOST_CH_SYNC) && + (conf->data_type != MOST_CH_ISOC_AVP)) { + dev_warn(dev, "Unsupported data type\n"); + return -EINVAL; + } + + frame_size = get_stream_frame_size(conf); + if ((frame_size == 0) || (frame_size > USB_MTU)) { + dev_warn(dev, "Misconfig: frame size wrong\n"); + return -EINVAL; + } + + if (conf->buffer_size % frame_size) { + u16 tmp_val; + + tmp_val = conf->buffer_size / frame_size; + conf->buffer_size = tmp_val * frame_size; + dev_notice(dev, + "Channel %d - rouding buffer size to %d bytes, " + "channel config says %d bytes\n", + channel, + conf->buffer_size, + temp_size); + } + + num_frames = conf->buffer_size / frame_size; + tail_space = num_frames * (USB_MTU - frame_size); + temp_size += tail_space; + + /* calculate extra length to comply w/ HW padding */ + conf->extra_len = (CEILING(temp_size, USB_MTU) * USB_MTU) + - conf->buffer_size; +exit: + mdev->conf[channel] = *conf; + return 0; +} + +/** + * hdm_update_netinfo - retrieve latest networking information + * @mdev: device interface + * + * This triggers the USB vendor requests to read the hardware address and + * the current link status of the attached device. + */ +int hdm_update_netinfo(struct most_dev *mdev) +{ + struct device *dev = &mdev->usb_device->dev; + int i; + u16 link; + u8 addr[6]; + + if (!is_valid_ether_addr(mdev->hw_addr)) { + if (0 > drci_rd_reg(mdev->usb_device, + DRCI_REG_HW_ADDR_HI, addr)) { + dev_err(dev, "Vendor request \"hw_addr_hi\" failed\n"); + return -1; + } + if (0 > drci_rd_reg(mdev->usb_device, + DRCI_REG_HW_ADDR_MI, addr + 2)) { + dev_err(dev, "Vendor request \"hw_addr_mid\" failed\n"); + return -1; + } + if (0 > drci_rd_reg(mdev->usb_device, + DRCI_REG_HW_ADDR_LO, addr + 4)) { + dev_err(dev, "Vendor request \"hw_addr_low\" failed\n"); + return -1; + } + mutex_lock(&mdev->io_mutex); + for (i = 0; i < 6; i++) + mdev->hw_addr[i] = addr[i]; + mutex_unlock(&mdev->io_mutex); + + } + if (0 > drci_rd_reg(mdev->usb_device, DRCI_REG_NI_STATE, &link)) { + dev_err(dev, "Vendor request \"link status\" failed\n"); + return -1; + } + le16_to_cpus(&link); + mutex_lock(&mdev->io_mutex); + mdev->link_stat = link; + mutex_unlock(&mdev->io_mutex); + return 0; +} + +/** + * hdm_request_netinfo - request network information + * @iface: pointer to interface + * @channel: channel ID + * + * This is used as trigger to set up the link status timer that + * polls for the NI state of the INIC every 2 seconds. + * + */ +void hdm_request_netinfo(struct most_interface *iface, int channel) +{ + struct most_dev *mdev; + + BUG_ON(!iface); + mdev = to_mdev(iface); + mdev->link_stat_timer.expires = jiffies + HZ; + mod_timer(&mdev->link_stat_timer, mdev->link_stat_timer.expires); +} + +/** + * link_stat_timer_handler - add work to link_stat work queue + * @data: pointer to USB device instance + * + * The handler runs in interrupt context. That's why we need to defer the + * tasks to a work queue. + */ +static void link_stat_timer_handler(unsigned long data) +{ + struct most_dev *mdev = (struct most_dev *)data; + + queue_work(schedule_usb_work, &mdev->poll_work_obj); + mdev->link_stat_timer.expires = jiffies + (2 * HZ); + add_timer(&mdev->link_stat_timer); +} + +/** + * wq_netinfo - work queue function + * @wq_obj: object that holds data for our deferred work to do + * + * This retrieves the network interface status of the USB INIC + * and compares it with the current status. If the status has + * changed, it updates the status of the core. + */ +static void wq_netinfo(struct work_struct *wq_obj) +{ + struct most_dev *mdev; + int i, prev_link_stat; + u8 prev_hw_addr[6]; + + mdev = to_mdev_from_work(wq_obj); + prev_link_stat = mdev->link_stat; + + for (i = 0; i < 6; i++) + prev_hw_addr[i] = mdev->hw_addr[i]; + + if (0 > hdm_update_netinfo(mdev)) + return; + if ((prev_link_stat != mdev->link_stat) || + (prev_hw_addr[0] != mdev->hw_addr[0]) || + (prev_hw_addr[1] != mdev->hw_addr[1]) || + (prev_hw_addr[2] != mdev->hw_addr[2]) || + (prev_hw_addr[3] != mdev->hw_addr[3]) || + (prev_hw_addr[4] != mdev->hw_addr[4]) || + (prev_hw_addr[5] != mdev->hw_addr[5])) + most_deliver_netinfo(&mdev->iface, mdev->link_stat, + &mdev->hw_addr[0]); +} + +/** + * wq_clear_halt - work queue function + * @wq_obj: work_struct object to execute + * + * This sends a clear_halt to the given USB pipe. + */ +static void wq_clear_halt(struct work_struct *wq_obj) +{ + struct buf_anchor *anchor; + struct most_dev *mdev; + struct mbo *mbo; + struct urb *urb; + unsigned int channel; + unsigned long flags; + + anchor = to_buf_anchor(wq_obj); + urb = anchor->urb; + mbo = urb->context; + mdev = to_mdev(mbo->ifp); + channel = mbo->hdm_channel_id; + + if (usb_clear_halt(urb->dev, urb->pipe)) + dev_warn(&mdev->usb_device->dev, "Failed to reset endpoint.\n"); + + usb_free_urb(urb); + spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); + list_del(&anchor->list); + spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); + + if (likely(mbo->complete)) + mbo->complete(mbo); + if (mdev->conf[channel].direction & MOST_CH_TX) + most_resume_enqueue(&mdev->iface, channel); + + kfree(anchor); +} + +/** + * hdm_usb_fops - file operation table for USB driver + */ +static const struct file_operations hdm_usb_fops = { + .owner = THIS_MODULE, +}; + +/** + * usb_device_id - ID table for HCD device probing + */ +static struct usb_device_id usbid[] = { + { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_BRDG), }, + { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_INIC), }, + { } /* Terminating entry */ +}; + +#define MOST_DCI_RO_ATTR(_name) \ + struct most_dci_attribute most_dci_attr_##_name = \ + __ATTR(_name, S_IRUGO, show_value, NULL) + +#define MOST_DCI_ATTR(_name) \ + struct most_dci_attribute most_dci_attr_##_name = \ + __ATTR(_name, S_IRUGO | S_IWUSR, show_value, store_value) + +/** + * struct most_dci_attribute - to access the attributes of a dci object + * @attr: attributes of a dci object + * @show: pointer to the show function + * @store: pointer to the store function + */ +struct most_dci_attribute { + struct attribute attr; + ssize_t (*show)(struct most_dci_obj *d, + struct most_dci_attribute *attr, + char *buf); + ssize_t (*store)(struct most_dci_obj *d, + struct most_dci_attribute *attr, + const char *buf, + size_t count); +}; +#define to_dci_attr(a) container_of(a, struct most_dci_attribute, attr) + + +/** + * dci_attr_show - show function for dci object + * @kobj: pointer to kobject + * @attr: pointer to attribute struct + * @buf: buffer + */ +static ssize_t dci_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct most_dci_attribute *dci_attr = to_dci_attr(attr); + struct most_dci_obj *dci_obj = to_dci_obj(kobj); + + if (!dci_attr->show) + return -EIO; + + return dci_attr->show(dci_obj, dci_attr, buf); +} + +/** + * dci_attr_store - store function for dci object + * @kobj: pointer to kobject + * @attr: pointer to attribute struct + * @buf: buffer + * @len: length of buffer + */ +static ssize_t dci_attr_store(struct kobject *kobj, + struct attribute *attr, + const char *buf, + size_t len) +{ + struct most_dci_attribute *dci_attr = to_dci_attr(attr); + struct most_dci_obj *dci_obj = to_dci_obj(kobj); + + if (!dci_attr->store) + return -EIO; + + return dci_attr->store(dci_obj, dci_attr, buf, len); +} + +static const struct sysfs_ops most_dci_sysfs_ops = { + .show = dci_attr_show, + .store = dci_attr_store, +}; + +/** + * most_dci_release - release function for dci object + * @kobj: pointer to kobject + * + * This frees the memory allocated for the dci object + */ +static void most_dci_release(struct kobject *kobj) +{ + struct most_dci_obj *dci_obj = to_dci_obj(kobj); + + kfree(dci_obj); +} + +static ssize_t show_value(struct most_dci_obj *dci_obj, + struct most_dci_attribute *attr, char *buf) +{ + u16 tmp_val; + u16 reg_addr; + int err; + + if (!strcmp(attr->attr.name, "ni_state")) + reg_addr = DRCI_REG_NI_STATE; + else if (!strcmp(attr->attr.name, "packet_bandwidth")) + reg_addr = DRCI_REG_PACKET_BW; + else if (!strcmp(attr->attr.name, "node_address")) + reg_addr = DRCI_REG_NODE_ADDR; + else if (!strcmp(attr->attr.name, "node_position")) + reg_addr = DRCI_REG_NODE_POS; + else if (!strcmp(attr->attr.name, "mep_filter")) + reg_addr = DRCI_REG_MEP_FILTER; + else if (!strcmp(attr->attr.name, "mep_hash0")) + reg_addr = DRCI_REG_HASH_TBL0; + else if (!strcmp(attr->attr.name, "mep_hash1")) + reg_addr = DRCI_REG_HASH_TBL1; + else if (!strcmp(attr->attr.name, "mep_hash2")) + reg_addr = DRCI_REG_HASH_TBL2; + else if (!strcmp(attr->attr.name, "mep_hash3")) + reg_addr = DRCI_REG_HASH_TBL3; + else if (!strcmp(attr->attr.name, "mep_eui48_hi")) + reg_addr = DRCI_REG_HW_ADDR_HI; + else if (!strcmp(attr->attr.name, "mep_eui48_mi")) + reg_addr = DRCI_REG_HW_ADDR_MI; + else if (!strcmp(attr->attr.name, "mep_eui48_lo")) + reg_addr = DRCI_REG_HW_ADDR_LO; + else + return -EIO; + + err = drci_rd_reg(dci_obj->usb_device, reg_addr, &tmp_val); + if (err < 0) + return err; + + return snprintf(buf, PAGE_SIZE, "%04x\n", le16_to_cpu(tmp_val)); +} + +static ssize_t store_value(struct most_dci_obj *dci_obj, + struct most_dci_attribute *attr, + const char *buf, size_t count) +{ + u16 v16; + u16 reg_addr; + int err; + + if (!strcmp(attr->attr.name, "mep_filter")) + reg_addr = DRCI_REG_MEP_FILTER; + else if (!strcmp(attr->attr.name, "mep_hash0")) + reg_addr = DRCI_REG_HASH_TBL0; + else if (!strcmp(attr->attr.name, "mep_hash1")) + reg_addr = DRCI_REG_HASH_TBL1; + else if (!strcmp(attr->attr.name, "mep_hash2")) + reg_addr = DRCI_REG_HASH_TBL2; + else if (!strcmp(attr->attr.name, "mep_hash3")) + reg_addr = DRCI_REG_HASH_TBL3; + else if (!strcmp(attr->attr.name, "mep_eui48_hi")) + reg_addr = DRCI_REG_HW_ADDR_HI; + else if (!strcmp(attr->attr.name, "mep_eui48_mi")) + reg_addr = DRCI_REG_HW_ADDR_MI; + else if (!strcmp(attr->attr.name, "mep_eui48_lo")) + reg_addr = DRCI_REG_HW_ADDR_LO; + else + return -EIO; + + err = kstrtou16(buf, 16, &v16); + if (err) + return err; + + err = drci_wr_reg(dci_obj->usb_device, reg_addr, cpu_to_le16(v16)); + if (err < 0) + return err; + + return count; +} + +static MOST_DCI_RO_ATTR(ni_state); +static MOST_DCI_RO_ATTR(packet_bandwidth); +static MOST_DCI_RO_ATTR(node_address); +static MOST_DCI_RO_ATTR(node_position); +static MOST_DCI_ATTR(mep_filter); +static MOST_DCI_ATTR(mep_hash0); +static MOST_DCI_ATTR(mep_hash1); +static MOST_DCI_ATTR(mep_hash2); +static MOST_DCI_ATTR(mep_hash3); +static MOST_DCI_ATTR(mep_eui48_hi); +static MOST_DCI_ATTR(mep_eui48_mi); +static MOST_DCI_ATTR(mep_eui48_lo); + +/** + * most_dci_def_attrs - array of default attribute files of the dci object + */ +static struct attribute *most_dci_def_attrs[] = { + &most_dci_attr_ni_state.attr, + &most_dci_attr_packet_bandwidth.attr, + &most_dci_attr_node_address.attr, + &most_dci_attr_node_position.attr, + &most_dci_attr_mep_filter.attr, + &most_dci_attr_mep_hash0.attr, + &most_dci_attr_mep_hash1.attr, + &most_dci_attr_mep_hash2.attr, + &most_dci_attr_mep_hash3.attr, + &most_dci_attr_mep_eui48_hi.attr, + &most_dci_attr_mep_eui48_mi.attr, + &most_dci_attr_mep_eui48_lo.attr, + NULL, +}; + +/** + * DCI ktype + */ +static struct kobj_type most_dci_ktype = { + .sysfs_ops = &most_dci_sysfs_ops, + .release = most_dci_release, + .default_attrs = most_dci_def_attrs, +}; + +/** + * create_most_dci_obj - allocates a dci object + * @parent: parent kobject + * + * This creates a dci object and registers it with sysfs. + * Returns a pointer to the object or NULL when something went wrong. + */ +static struct +most_dci_obj *create_most_dci_obj(struct kobject *parent) +{ + struct most_dci_obj *most_dci; + int retval; + + most_dci = kzalloc(sizeof(*most_dci), GFP_KERNEL); + if (!most_dci) + return NULL; + + retval = kobject_init_and_add(&most_dci->kobj, &most_dci_ktype, parent, + "dci"); + if (retval) { + kobject_put(&most_dci->kobj); + return NULL; + } + return most_dci; +} + +/** + * destroy_most_dci_obj - DCI object release function + * @p: pointer to dci object + */ +static void destroy_most_dci_obj(struct most_dci_obj *p) +{ + kobject_put(&p->kobj); +} + +/** + * hdm_probe - probe function of USB device driver + * @interface: Interface of the attached USB device + * @id: Pointer to the USB ID table. + * + * This allocates and initializes the device instance, adds the new + * entry to the internal list, scans the USB descriptors and registers + * the interface with the core. + * Additionally, the DCI objects are created and the hardware is sync'd. + * + * Return 0 on success. In case of an error a negative number is returned. + */ +static int +hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) +{ + unsigned int i; + unsigned int num_endpoints; + struct most_channel_capability *tmp_cap; + struct most_dev *mdev; + struct usb_device *usb_dev; + struct device *dev; + struct usb_host_interface *usb_iface_desc; + struct usb_endpoint_descriptor *ep_desc; + int ret = 0; + + usb_iface_desc = interface->cur_altsetting; + usb_dev = interface_to_usbdev(interface); + dev = &usb_dev->dev; + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + if (!mdev) + goto exit_ENOMEM; + + usb_set_intfdata(interface, mdev); + num_endpoints = usb_iface_desc->desc.bNumEndpoints; + mutex_init(&mdev->io_mutex); + INIT_WORK(&mdev->poll_work_obj, wq_netinfo); + init_timer(&mdev->link_stat_timer); + + mdev->usb_device = usb_dev; + mdev->link_stat_timer.function = link_stat_timer_handler; + mdev->link_stat_timer.data = (unsigned long)mdev; + mdev->link_stat_timer.expires = jiffies + (2 * HZ); + + mdev->iface.mod = hdm_usb_fops.owner; + mdev->iface.interface = ITYPE_USB; + mdev->iface.configure = hdm_configure_channel; + mdev->iface.request_netinfo = hdm_request_netinfo; + mdev->iface.enqueue = hdm_enqueue; + mdev->iface.poison_channel = hdm_poison_channel; + mdev->iface.description = mdev->description; + mdev->iface.num_channels = num_endpoints; + + snprintf(mdev->description, sizeof(mdev->description), + "usb_device %d-%s:%d.%d", + usb_dev->bus->busnum, + usb_dev->devpath, + usb_dev->config->desc.bConfigurationValue, + usb_iface_desc->desc.bInterfaceNumber); + + mdev->conf = kcalloc(num_endpoints, sizeof(*mdev->conf), GFP_KERNEL); + if (!mdev->conf) + goto exit_free; + + mdev->cap = kcalloc(num_endpoints, sizeof(*mdev->cap), GFP_KERNEL); + if (!mdev->cap) + goto exit_free1; + + mdev->iface.channel_vector = mdev->cap; + mdev->iface.priv = NULL; + + mdev->ep_address = + kcalloc(num_endpoints, sizeof(*mdev->ep_address), GFP_KERNEL); + if (!mdev->ep_address) + goto exit_free2; + + mdev->anchor_list = + kcalloc(num_endpoints, sizeof(*mdev->anchor_list), GFP_KERNEL); + if (!mdev->anchor_list) + goto exit_free3; + + tmp_cap = mdev->cap; + for (i = 0; i < num_endpoints; i++) { + ep_desc = &usb_iface_desc->endpoint[i].desc; + mdev->ep_address[i] = ep_desc->bEndpointAddress; + mdev->padding_active[i] = false; + mdev->is_channel_healthy[i] = true; + + snprintf(&mdev->suffix[i][0], MAX_SUFFIX_LEN, "ep%02x", + mdev->ep_address[i]); + + tmp_cap->name_suffix = &mdev->suffix[i][0]; + tmp_cap->buffer_size_packet = MAX_BUF_SIZE; + tmp_cap->buffer_size_streaming = MAX_BUF_SIZE; + tmp_cap->num_buffers_packet = BUF_CHAIN_SIZE; + tmp_cap->num_buffers_streaming = BUF_CHAIN_SIZE; + tmp_cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC | + MOST_CH_ISOC_AVP | MOST_CH_SYNC; + if (ep_desc->bEndpointAddress & USB_DIR_IN) + tmp_cap->direction = MOST_CH_RX; + else + tmp_cap->direction = MOST_CH_TX; + tmp_cap++; + INIT_LIST_HEAD(&mdev->anchor_list[i]); + spin_lock_init(&mdev->anchor_list_lock[i]); + } + dev_notice(dev, "claimed gadget: Vendor=%4.4x ProdID=%4.4x Bus=%02x Device=%02x\n", + le16_to_cpu(usb_dev->descriptor.idVendor), + le16_to_cpu(usb_dev->descriptor.idProduct), + usb_dev->bus->busnum, + usb_dev->devnum); + + dev_notice(dev, "device path: /sys/bus/usb/devices/%d-%s:%d.%d\n", + usb_dev->bus->busnum, + usb_dev->devpath, + usb_dev->config->desc.bConfigurationValue, + usb_iface_desc->desc.bInterfaceNumber); + + mdev->parent = most_register_interface(&mdev->iface); + if (IS_ERR(mdev->parent)) { + ret = PTR_ERR(mdev->parent); + goto exit_free4; + } + + mutex_lock(&mdev->io_mutex); + if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_INIC) { + /* this increments the reference count of the instance + * object of the core + */ + mdev->dci = create_most_dci_obj(mdev->parent); + if (!mdev->dci) { + mutex_unlock(&mdev->io_mutex); + most_deregister_interface(&mdev->iface); + ret = -ENOMEM; + goto exit_free4; + } + + kobject_uevent(&mdev->dci->kobj, KOBJ_ADD); + mdev->dci->usb_device = mdev->usb_device; + trigger_resync_vr(usb_dev); + } + mutex_unlock(&mdev->io_mutex); + return 0; + +exit_free4: + kfree(mdev->anchor_list); +exit_free3: + kfree(mdev->ep_address); +exit_free2: + kfree(mdev->cap); +exit_free1: + kfree(mdev->conf); +exit_free: + kfree(mdev); +exit_ENOMEM: + if (ret == 0 || ret == -ENOMEM) { + ret = -ENOMEM; + dev_err(dev, "out of memory\n"); + } + return ret; +} + +/** + * hdm_disconnect - disconnect function of USB device driver + * @interface: Interface of the attached USB device + * + * This deregisters the interface with the core, removes the kernel timer + * and frees resources. + * + * Context: hub kernel thread + */ +static void hdm_disconnect(struct usb_interface *interface) +{ + struct most_dev *mdev; + + mdev = usb_get_intfdata(interface); + mutex_lock(&mdev->io_mutex); + usb_set_intfdata(interface, NULL); + mdev->usb_device = NULL; + mutex_unlock(&mdev->io_mutex); + + del_timer_sync(&mdev->link_stat_timer); + cancel_work_sync(&mdev->poll_work_obj); + + destroy_most_dci_obj(mdev->dci); + most_deregister_interface(&mdev->iface); + + kfree(mdev->anchor_list); + kfree(mdev->cap); + kfree(mdev->conf); + kfree(mdev->ep_address); + kfree(mdev); +} + +static struct usb_driver hdm_usb = { + .name = "hdm_usb", + .id_table = usbid, + .probe = hdm_probe, + .disconnect = hdm_disconnect, +}; + +static int __init hdm_usb_init(void) +{ + pr_info("hdm_usb_init()\n"); + if (usb_register(&hdm_usb)) { + pr_err("could not register hdm_usb driver\n"); + return -EIO; + } + schedule_usb_work = create_workqueue("hdmu_work"); + if (schedule_usb_work == NULL) { + pr_err("could not create workqueue\n"); + usb_deregister(&hdm_usb); + return -ENOMEM; + } + return 0; +} + +static void __exit hdm_usb_exit(void) +{ + pr_info("hdm_usb_exit()\n"); + destroy_workqueue(schedule_usb_work); + usb_deregister(&hdm_usb); +} + +module_init(hdm_usb_init); +module_exit(hdm_usb_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>"); +MODULE_DESCRIPTION("HDM_4_USB"); diff --git a/drivers/staging/most/mostcore/Kconfig b/drivers/staging/most/mostcore/Kconfig new file mode 100644 index 000000000000..38abf1b21b66 --- /dev/null +++ b/drivers/staging/most/mostcore/Kconfig @@ -0,0 +1,13 @@ +# +# MOSTCore configuration +# + +config MOSTCORE + tristate "MOST Core" + + ---help--- + Say Y here if you want to enable MOST support. + This device driver needs at least an additional AIM and HDM to work. + + To compile this driver as a module, choose M here: the + module will be called mostcore. diff --git a/drivers/staging/most/mostcore/Makefile b/drivers/staging/most/mostcore/Makefile new file mode 100644 index 000000000000..a078f01cf7c2 --- /dev/null +++ b/drivers/staging/most/mostcore/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_MOSTCORE) += mostcore.o + +mostcore-objs := core.o diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c new file mode 100644 index 000000000000..f4fea8cf5560 --- /dev/null +++ b/drivers/staging/most/mostcore/core.c @@ -0,0 +1,1931 @@ +/* + * core.c - Implementation of core module of MOST Linux driver stack + * + * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This file is licensed under GPLv2. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/module.h> +#include <linux/fs.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/device.h> +#include <linux/list.h> +#include <linux/poll.h> +#include <linux/wait.h> +#include <linux/kobject.h> +#include <linux/mutex.h> +#include <linux/completion.h> +#include <linux/sysfs.h> +#include <linux/kthread.h> +#include <linux/dma-mapping.h> +#include <linux/idr.h> +#include "mostcore.h" + +#define MAX_CHANNELS 64 +#define STRING_SIZE 80 + +static struct class *most_class; +static struct device *class_glue_dir; +static struct ida mdev_id; +static int modref; + +struct most_c_obj { + struct kobject kobj; + struct completion cleanup; + atomic_t mbo_ref; + atomic_t mbo_nq_level; + uint16_t channel_id; + bool is_poisoned; + bool is_started; + int is_starving; + struct most_interface *iface; + struct most_inst_obj *inst; + struct most_channel_config cfg; + bool keep_mbo; + bool enqueue_halt; + struct list_head fifo; + spinlock_t fifo_lock; + struct list_head halt_fifo; + struct list_head list; + struct most_aim *first_aim; + struct most_aim *second_aim; + struct list_head trash_fifo; + struct task_struct *hdm_enqueue_task; + struct mutex stop_task_mutex; + wait_queue_head_t hdm_fifo_wq; +}; +#define to_c_obj(d) container_of(d, struct most_c_obj, kobj) + +struct most_inst_obj { + int dev_id; + atomic_t tainted; + struct most_interface *iface; + struct list_head channel_list; + struct most_c_obj *channel[MAX_CHANNELS]; + struct kobject kobj; + struct list_head list; +}; +#define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj) + +/** + * list_pop_mbo - retrieves the first MBO of the list and removes it + * @ptr: the list head to grab the MBO from. + */ +#define list_pop_mbo(ptr) \ +({ \ + struct mbo *_mbo = list_first_entry(ptr, struct mbo, list); \ + list_del(&_mbo->list); \ + _mbo; \ +}) + +static struct mutex deregister_mutex; + +/* ___ ___ + * ___C H A N N E L___ + */ + +/** + * struct most_c_attr - to access the attributes of a channel object + * @attr: attributes of a channel + * @show: pointer to the show function + * @store: pointer to the store function + */ +struct most_c_attr { + struct attribute attr; + ssize_t (*show)(struct most_c_obj *d, + struct most_c_attr *attr, + char *buf); + ssize_t (*store)(struct most_c_obj *d, + struct most_c_attr *attr, + const char *buf, + size_t count); +}; +#define to_channel_attr(a) container_of(a, struct most_c_attr, attr) + +#define MOST_CHNL_ATTR(_name, _mode, _show, _store) \ + struct most_c_attr most_chnl_attr_##_name = \ + __ATTR(_name, _mode, _show, _store) + +/** + * channel_attr_show - show function of channel object + * @kobj: pointer to its kobject + * @attr: pointer to its attributes + * @buf: buffer + */ +static ssize_t channel_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct most_c_attr *channel_attr = to_channel_attr(attr); + struct most_c_obj *c_obj = to_c_obj(kobj); + + if (!channel_attr->show) + return -EIO; + + return channel_attr->show(c_obj, channel_attr, buf); +} + +/** + * channel_attr_store - store function of channel object + * @kobj: pointer to its kobject + * @attr: pointer to its attributes + * @buf: buffer + * @len: length of buffer + */ +static ssize_t channel_attr_store(struct kobject *kobj, + struct attribute *attr, + const char *buf, + size_t len) +{ + struct most_c_attr *channel_attr = to_channel_attr(attr); + struct most_c_obj *c_obj = to_c_obj(kobj); + + if (!channel_attr->store) + return -EIO; + return channel_attr->store(c_obj, channel_attr, buf, len); +} + +static const struct sysfs_ops most_channel_sysfs_ops = { + .show = channel_attr_show, + .store = channel_attr_store, +}; + +/** + * most_free_mbo_coherent - free an MBO and its coherent buffer + * @mbo: buffer to be released + * + */ +static void most_free_mbo_coherent(struct mbo *mbo) +{ + struct most_c_obj *c = mbo->context; + u16 const coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len; + + dma_free_coherent(NULL, coherent_buf_size, mbo->virt_address, + mbo->bus_address); + kfree(mbo); + if (atomic_sub_and_test(1, &c->mbo_ref)) + complete(&c->cleanup); +} + +/** + * flush_channel_fifos - clear the channel fifos + * @c: pointer to channel object + */ +void flush_channel_fifos(struct most_c_obj *c) +{ + unsigned long flags, hf_flags; + struct mbo *mbo, *tmp; + + if (list_empty(&c->fifo) && list_empty(&c->halt_fifo)) + return; + + spin_lock_irqsave(&c->fifo_lock, flags); + list_for_each_entry_safe(mbo, tmp, &c->fifo, list) { + list_del(&mbo->list); + spin_unlock_irqrestore(&c->fifo_lock, flags); + if (likely(mbo)) + most_free_mbo_coherent(mbo); + spin_lock_irqsave(&c->fifo_lock, flags); + } + spin_unlock_irqrestore(&c->fifo_lock, flags); + + spin_lock_irqsave(&c->fifo_lock, hf_flags); + list_for_each_entry_safe(mbo, tmp, &c->halt_fifo, list) { + list_del(&mbo->list); + spin_unlock_irqrestore(&c->fifo_lock, hf_flags); + if (likely(mbo)) + most_free_mbo_coherent(mbo); + spin_lock_irqsave(&c->fifo_lock, hf_flags); + } + spin_unlock_irqrestore(&c->fifo_lock, hf_flags); + + if (unlikely((!list_empty(&c->fifo) || !list_empty(&c->halt_fifo)))) + pr_info("WARN: fifo | trash fifo not empty\n"); +} + +/** + * flush_trash_fifo - clear the trash fifo + * @c: pointer to channel object + */ +static int flush_trash_fifo(struct most_c_obj *c) +{ + struct mbo *mbo, *tmp; + unsigned long flags; + + spin_lock_irqsave(&c->fifo_lock, flags); + list_for_each_entry_safe(mbo, tmp, &c->trash_fifo, list) { + list_del(&mbo->list); + spin_unlock_irqrestore(&c->fifo_lock, flags); + most_free_mbo_coherent(mbo); + spin_lock_irqsave(&c->fifo_lock, flags); + } + spin_unlock_irqrestore(&c->fifo_lock, flags); + return 0; +} + +/** + * most_channel_release - release function of channel object + * @kobj: pointer to channel's kobject + */ +static void most_channel_release(struct kobject *kobj) +{ + struct most_c_obj *c = to_c_obj(kobj); + + kfree(c); +} + +static ssize_t show_available_directions(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + unsigned int i = c->channel_id; + + strcpy(buf, ""); + if (c->iface->channel_vector[i].direction & MOST_CH_RX) + strcat(buf, "dir_rx "); + if (c->iface->channel_vector[i].direction & MOST_CH_TX) + strcat(buf, "dir_tx "); + strcat(buf, "\n"); + return strlen(buf) + 1; +} + +static ssize_t show_available_datatypes(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + unsigned int i = c->channel_id; + + strcpy(buf, ""); + if (c->iface->channel_vector[i].data_type & MOST_CH_CONTROL) + strcat(buf, "control "); + if (c->iface->channel_vector[i].data_type & MOST_CH_ASYNC) + strcat(buf, "async "); + if (c->iface->channel_vector[i].data_type & MOST_CH_SYNC) + strcat(buf, "sync "); + if (c->iface->channel_vector[i].data_type & MOST_CH_ISOC_AVP) + strcat(buf, "isoc_avp "); + strcat(buf, "\n"); + return strlen(buf) + 1; +} + +static +ssize_t show_number_of_packet_buffers(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + unsigned int i = c->channel_id; + + return snprintf(buf, PAGE_SIZE, "%d\n", + c->iface->channel_vector[i].num_buffers_packet); +} + +static +ssize_t show_number_of_stream_buffers(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + unsigned int i = c->channel_id; + + return snprintf(buf, PAGE_SIZE, "%d\n", + c->iface->channel_vector[i].num_buffers_streaming); +} + +static +ssize_t show_size_of_packet_buffer(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + unsigned int i = c->channel_id; + + return snprintf(buf, PAGE_SIZE, "%d\n", + c->iface->channel_vector[i].buffer_size_packet); +} + +static +ssize_t show_size_of_stream_buffer(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + unsigned int i = c->channel_id; + + return snprintf(buf, PAGE_SIZE, "%d\n", + c->iface->channel_vector[i].buffer_size_streaming); +} + +static ssize_t show_channel_starving(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", c->is_starving); +} + + +#define create_show_channel_attribute(val) \ + static MOST_CHNL_ATTR(val, S_IRUGO, show_##val, NULL) + +create_show_channel_attribute(available_directions); +create_show_channel_attribute(available_datatypes); +create_show_channel_attribute(number_of_packet_buffers); +create_show_channel_attribute(number_of_stream_buffers); +create_show_channel_attribute(size_of_stream_buffer); +create_show_channel_attribute(size_of_packet_buffer); +create_show_channel_attribute(channel_starving); + +static ssize_t show_set_number_of_buffers(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.num_buffers); +} + +static ssize_t store_set_number_of_buffers(struct most_c_obj *c, + struct most_c_attr *attr, + const char *buf, + size_t count) +{ + int ret = kstrtou16(buf, 0, &c->cfg.num_buffers); + + if (ret) + return ret; + return count; +} + +static ssize_t show_set_buffer_size(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.buffer_size); +} + +static ssize_t store_set_buffer_size(struct most_c_obj *c, + struct most_c_attr *attr, + const char *buf, + size_t count) +{ + int ret = kstrtou16(buf, 0, &c->cfg.buffer_size); + + if (ret) + return ret; + return count; +} + +static ssize_t show_set_direction(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + if (c->cfg.direction & MOST_CH_TX) + return snprintf(buf, PAGE_SIZE, "dir_tx\n"); + else if (c->cfg.direction & MOST_CH_RX) + return snprintf(buf, PAGE_SIZE, "dir_rx\n"); + return snprintf(buf, PAGE_SIZE, "unconfigured\n"); +} + +static ssize_t store_set_direction(struct most_c_obj *c, + struct most_c_attr *attr, + const char *buf, + size_t count) +{ + if (!strcmp(buf, "dir_rx\n")) + c->cfg.direction = MOST_CH_RX; + else if (!strcmp(buf, "dir_tx\n")) + c->cfg.direction = MOST_CH_TX; + else { + pr_info("WARN: invalid attribute settings\n"); + return -EINVAL; + } + return count; +} + +static ssize_t show_set_datatype(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + if (c->cfg.data_type & MOST_CH_CONTROL) + return snprintf(buf, PAGE_SIZE, "control\n"); + else if (c->cfg.data_type & MOST_CH_ASYNC) + return snprintf(buf, PAGE_SIZE, "async\n"); + else if (c->cfg.data_type & MOST_CH_SYNC) + return snprintf(buf, PAGE_SIZE, "sync\n"); + else if (c->cfg.data_type & MOST_CH_ISOC_AVP) + return snprintf(buf, PAGE_SIZE, "isoc_avp\n"); + return snprintf(buf, PAGE_SIZE, "unconfigured\n"); +} + +static ssize_t store_set_datatype(struct most_c_obj *c, + struct most_c_attr *attr, + const char *buf, + size_t count) +{ + if (!strcmp(buf, "control\n")) + c->cfg.data_type = MOST_CH_CONTROL; + else if (!strcmp(buf, "async\n")) + c->cfg.data_type = MOST_CH_ASYNC; + else if (!strcmp(buf, "sync\n")) + c->cfg.data_type = MOST_CH_SYNC; + else if (!strcmp(buf, "isoc_avp\n")) + c->cfg.data_type = MOST_CH_ISOC_AVP; + else { + pr_info("WARN: invalid attribute settings\n"); + return -EINVAL; + } + return count; +} + +static ssize_t show_set_subbuffer_size(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.subbuffer_size); +} + +static ssize_t store_set_subbuffer_size(struct most_c_obj *c, + struct most_c_attr *attr, + const char *buf, + size_t count) +{ + int ret = kstrtou16(buf, 0, &c->cfg.subbuffer_size); + + if (ret) + return ret; + return count; +} + +static ssize_t show_set_packets_per_xact(struct most_c_obj *c, + struct most_c_attr *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.packets_per_xact); +} + +static ssize_t store_set_packets_per_xact(struct most_c_obj *c, + struct most_c_attr *attr, + const char *buf, + size_t count) +{ + int ret = kstrtou16(buf, 0, &c->cfg.packets_per_xact); + + if (ret) + return ret; + return count; +} + +#define create_channel_attribute(value) \ + static MOST_CHNL_ATTR(value, S_IRUGO | S_IWUSR, \ + show_##value, \ + store_##value) + +create_channel_attribute(set_buffer_size); +create_channel_attribute(set_number_of_buffers); +create_channel_attribute(set_direction); +create_channel_attribute(set_datatype); +create_channel_attribute(set_subbuffer_size); +create_channel_attribute(set_packets_per_xact); + + +/** + * most_channel_def_attrs - array of default attributes of channel object + */ +static struct attribute *most_channel_def_attrs[] = { + &most_chnl_attr_available_directions.attr, + &most_chnl_attr_available_datatypes.attr, + &most_chnl_attr_number_of_packet_buffers.attr, + &most_chnl_attr_number_of_stream_buffers.attr, + &most_chnl_attr_size_of_packet_buffer.attr, + &most_chnl_attr_size_of_stream_buffer.attr, + &most_chnl_attr_set_number_of_buffers.attr, + &most_chnl_attr_set_buffer_size.attr, + &most_chnl_attr_set_direction.attr, + &most_chnl_attr_set_datatype.attr, + &most_chnl_attr_set_subbuffer_size.attr, + &most_chnl_attr_set_packets_per_xact.attr, + &most_chnl_attr_channel_starving.attr, + NULL, +}; + +static struct kobj_type most_channel_ktype = { + .sysfs_ops = &most_channel_sysfs_ops, + .release = most_channel_release, + .default_attrs = most_channel_def_attrs, +}; + +static struct kset *most_channel_kset; + +/** + * create_most_c_obj - allocates a channel object + * @name: name of the channel object + * @parent: parent kobject + * + * This create a channel object and registers it with sysfs. + * Returns a pointer to the object or NULL when something went wrong. + */ +static struct most_c_obj * +create_most_c_obj(const char *name, struct kobject *parent) +{ + struct most_c_obj *c; + int retval; + + c = kzalloc(sizeof(*c), GFP_KERNEL); + if (!c) + return NULL; + c->kobj.kset = most_channel_kset; + retval = kobject_init_and_add(&c->kobj, &most_channel_ktype, parent, + "%s", name); + if (retval) { + kobject_put(&c->kobj); + return NULL; + } + kobject_uevent(&c->kobj, KOBJ_ADD); + return c; +} + +/** + * destroy_most_c_obj - channel release function + * @c: pointer to channel object + * + * This decrements the reference counter of the channel object. + * If the reference count turns zero, its release function is called. + */ +static void destroy_most_c_obj(struct most_c_obj *c) +{ + if (c->first_aim) + c->first_aim->disconnect_channel(c->iface, c->channel_id); + if (c->second_aim) + c->second_aim->disconnect_channel(c->iface, c->channel_id); + c->first_aim = NULL; + c->second_aim = NULL; + + mutex_lock(&deregister_mutex); + flush_trash_fifo(c); + flush_channel_fifos(c); + mutex_unlock(&deregister_mutex); + kobject_put(&c->kobj); +} + +/* ___ ___ + * ___I N S T A N C E___ + */ +#define MOST_INST_ATTR(_name, _mode, _show, _store) \ + struct most_inst_attribute most_inst_attr_##_name = \ + __ATTR(_name, _mode, _show, _store) + +static struct list_head instance_list; + +/** + * struct most_inst_attribute - to access the attributes of instance object + * @attr: attributes of an instance + * @show: pointer to the show function + * @store: pointer to the store function + */ +struct most_inst_attribute { + struct attribute attr; + ssize_t (*show)(struct most_inst_obj *d, + struct most_inst_attribute *attr, + char *buf); + ssize_t (*store)(struct most_inst_obj *d, + struct most_inst_attribute *attr, + const char *buf, + size_t count); +}; +#define to_instance_attr(a) \ + container_of(a, struct most_inst_attribute, attr) + +/** + * instance_attr_show - show function for an instance object + * @kobj: pointer to kobject + * @attr: pointer to attribute struct + * @buf: buffer + */ +static ssize_t instance_attr_show(struct kobject *kobj, + struct attribute *attr, + char *buf) +{ + struct most_inst_attribute *instance_attr; + struct most_inst_obj *instance_obj; + + instance_attr = to_instance_attr(attr); + instance_obj = to_inst_obj(kobj); + + if (!instance_attr->show) + return -EIO; + + return instance_attr->show(instance_obj, instance_attr, buf); +} + +/** + * instance_attr_store - store function for an instance object + * @kobj: pointer to kobject + * @attr: pointer to attribute struct + * @buf: buffer + * @len: length of buffer + */ +static ssize_t instance_attr_store(struct kobject *kobj, + struct attribute *attr, + const char *buf, + size_t len) +{ + struct most_inst_attribute *instance_attr; + struct most_inst_obj *instance_obj; + + instance_attr = to_instance_attr(attr); + instance_obj = to_inst_obj(kobj); + + if (!instance_attr->store) + return -EIO; + + return instance_attr->store(instance_obj, instance_attr, buf, len); +} + +static const struct sysfs_ops most_inst_sysfs_ops = { + .show = instance_attr_show, + .store = instance_attr_store, +}; + +/** + * most_inst_release - release function for instance object + * @kobj: pointer to instance's kobject + * + * This frees the allocated memory for the instance object + */ +static void most_inst_release(struct kobject *kobj) +{ + struct most_inst_obj *inst = to_inst_obj(kobj); + + kfree(inst); +} + +static ssize_t show_description(struct most_inst_obj *instance_obj, + struct most_inst_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%s\n", + instance_obj->iface->description); +} + +static ssize_t show_interface(struct most_inst_obj *instance_obj, + struct most_inst_attribute *attr, + char *buf) +{ + switch (instance_obj->iface->interface) { + case ITYPE_LOOPBACK: + return snprintf(buf, PAGE_SIZE, "loopback\n"); + case ITYPE_I2C: + return snprintf(buf, PAGE_SIZE, "i2c\n"); + case ITYPE_I2S: + return snprintf(buf, PAGE_SIZE, "i2s\n"); + case ITYPE_TSI: + return snprintf(buf, PAGE_SIZE, "tsi\n"); + case ITYPE_HBI: + return snprintf(buf, PAGE_SIZE, "hbi\n"); + case ITYPE_MEDIALB_DIM: + return snprintf(buf, PAGE_SIZE, "mlb_dim\n"); + case ITYPE_MEDIALB_DIM2: + return snprintf(buf, PAGE_SIZE, "mlb_dim2\n"); + case ITYPE_USB: + return snprintf(buf, PAGE_SIZE, "usb\n"); + case ITYPE_PCIE: + return snprintf(buf, PAGE_SIZE, "pcie\n"); + } + return snprintf(buf, PAGE_SIZE, "unknown\n"); +} + +#define create_inst_attribute(value) \ + static MOST_INST_ATTR(value, S_IRUGO, show_##value, NULL) + +create_inst_attribute(description); +create_inst_attribute(interface); + +static struct attribute *most_inst_def_attrs[] = { + &most_inst_attr_description.attr, + &most_inst_attr_interface.attr, + NULL, +}; + +static struct kobj_type most_inst_ktype = { + .sysfs_ops = &most_inst_sysfs_ops, + .release = most_inst_release, + .default_attrs = most_inst_def_attrs, +}; + +static struct kset *most_inst_kset; + + +/** + * create_most_inst_obj - creates an instance object + * @name: name of the object to be created + * + * This allocates memory for an instance structure, assigns the proper kset + * and registers it with sysfs. + * + * Returns a pointer to the instance object or NULL when something went wrong. + */ +static struct most_inst_obj *create_most_inst_obj(const char *name) +{ + struct most_inst_obj *inst; + int retval; + + inst = kzalloc(sizeof(*inst), GFP_KERNEL); + if (!inst) + return NULL; + inst->kobj.kset = most_inst_kset; + retval = kobject_init_and_add(&inst->kobj, &most_inst_ktype, NULL, + "%s", name); + if (retval) { + kobject_put(&inst->kobj); + return NULL; + } + kobject_uevent(&inst->kobj, KOBJ_ADD); + return inst; +} + +/** + * destroy_most_inst_obj - MOST instance release function + * @inst: pointer to the instance object + * + * This decrements the reference counter of the instance object. + * If the reference count turns zero, its release function is called + */ +static void destroy_most_inst_obj(struct most_inst_obj *inst) +{ + struct most_c_obj *c, *tmp; + + /* need to destroy channels first, since + * each channel incremented the + * reference count of the inst->kobj + */ + list_for_each_entry_safe(c, tmp, &inst->channel_list, list) { + destroy_most_c_obj(c); + } + kobject_put(&inst->kobj); +} + +/* ___ ___ + * ___A I M___ + */ +struct most_aim_obj { + struct kobject kobj; + struct list_head list; + struct most_aim *driver; + char add_link[STRING_SIZE]; + char remove_link[STRING_SIZE]; +}; +#define to_aim_obj(d) container_of(d, struct most_aim_obj, kobj) + +static struct list_head aim_list; + + +/** + * struct most_aim_attribute - to access the attributes of AIM object + * @attr: attributes of an AIM + * @show: pointer to the show function + * @store: pointer to the store function + */ +struct most_aim_attribute { + struct attribute attr; + ssize_t (*show)(struct most_aim_obj *d, + struct most_aim_attribute *attr, + char *buf); + ssize_t (*store)(struct most_aim_obj *d, + struct most_aim_attribute *attr, + const char *buf, + size_t count); +}; +#define to_aim_attr(a) container_of(a, struct most_aim_attribute, attr) + +/** + * aim_attr_show - show function of an AIM object + * @kobj: pointer to kobject + * @attr: pointer to attribute struct + * @buf: buffer + */ +static ssize_t aim_attr_show(struct kobject *kobj, + struct attribute *attr, + char *buf) +{ + struct most_aim_attribute *aim_attr; + struct most_aim_obj *aim_obj; + + aim_attr = to_aim_attr(attr); + aim_obj = to_aim_obj(kobj); + + if (!aim_attr->show) + return -EIO; + + return aim_attr->show(aim_obj, aim_attr, buf); +} + +/** + * aim_attr_store - store function of an AIM object + * @kobj: pointer to kobject + * @attr: pointer to attribute struct + * @buf: buffer + * @len: length of buffer + */ +static ssize_t aim_attr_store(struct kobject *kobj, + struct attribute *attr, + const char *buf, + size_t len) +{ + struct most_aim_attribute *aim_attr; + struct most_aim_obj *aim_obj; + + aim_attr = to_aim_attr(attr); + aim_obj = to_aim_obj(kobj); + + if (!aim_attr->store) + return -EIO; + return aim_attr->store(aim_obj, aim_attr, buf, len); +} + +static const struct sysfs_ops most_aim_sysfs_ops = { + .show = aim_attr_show, + .store = aim_attr_store, +}; + +/** + * most_aim_release - AIM release function + * @kobj: pointer to AIM's kobject + */ +static void most_aim_release(struct kobject *kobj) +{ + struct most_aim_obj *aim_obj = to_aim_obj(kobj); + + kfree(aim_obj); +} + +static ssize_t show_add_link(struct most_aim_obj *aim_obj, + struct most_aim_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%s\n", aim_obj->add_link); +} + +/** + * split_string - parses and changes string in the buffer buf and + * splits it into two mandatory and one optional substrings. + * + * @buf: complete string from attribute 'add_channel' + * @a: address of pointer to 1st substring (=instance name) + * @b: address of pointer to 2nd substring (=channel name) + * @c: optional address of pointer to 3rd substring (=user defined name) + * + * Examples: + * + * Input: "mdev0:ch0@ep_81:my_channel\n" or + * "mdev0:ch0@ep_81:my_channel" + * + * Output: *a -> "mdev0", *b -> "ch0@ep_81", *c -> "my_channel" + * + * Input: "mdev0:ch0@ep_81\n" + * Output: *a -> "mdev0", *b -> "ch0@ep_81", *c -> "" + * + * Input: "mdev0:ch0@ep_81" + * Output: *a -> "mdev0", *b -> "ch0@ep_81", *c == NULL + */ +int split_string(char *buf, char **a, char **b, char **c) +{ + *a = strsep(&buf, ":"); + if (!*a) + return -EIO; + + *b = strsep(&buf, ":\n"); + if (!*b) + return -EIO; + + if (c) + *c = strsep(&buf, ":\n"); + + return 0; +} + +/** + * get_channel_by_name - get pointer to channel object + * @mdev: name of the device instance + * @mdev_ch: name of the respective channel + * + * This retrieves the pointer to a channel object. + */ +static struct +most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch) +{ + struct most_c_obj *c, *tmp; + struct most_inst_obj *i, *i_tmp; + int found = 0; + + list_for_each_entry_safe(i, i_tmp, &instance_list, list) { + if (!strcmp(kobject_name(&i->kobj), mdev)) { + found++; + break; + } + } + if (unlikely(!found)) + return ERR_PTR(-EIO); + + list_for_each_entry_safe(c, tmp, &i->channel_list, list) { + if (!strcmp(kobject_name(&c->kobj), mdev_ch)) { + found++; + break; + } + } + if (unlikely(2 > found)) + return ERR_PTR(-EIO); + return c; +} + +/** + * store_add_link - store() function for add_link attribute + * @aim_obj: pointer to AIM object + * @attr: its attributes + * @buf: buffer + * @len: buffer length + * + * This parses the string given by buf and splits it into + * three substrings. Note: third substring is optional. In case a cdev + * AIM is loaded the optional 3rd substring will make up the name of + * device node in the /dev directory. If omitted, the device node will + * inherit the channel's name within sysfs. + * + * Searches for a pair of device and channel and probes the AIM + * + * Example: + * (1) echo -n -e "mdev0:ch0@ep_81:my_rxchannel\n" >add_link + * (2) echo -n -e "mdev0:ch0@ep_81\n" >add_link + * + * (1) would create the device node /dev/my_rxchannel + * (2) would create the device node /dev/mdev0-ch0@ep_81 + */ +static ssize_t store_add_link(struct most_aim_obj *aim_obj, + struct most_aim_attribute *attr, + const char *buf, + size_t len) +{ + struct most_c_obj *c; + struct most_aim **aim_ptr; + char buffer[STRING_SIZE]; + char *mdev; + char *mdev_ch; + char *mdev_devnod; + char devnod_buf[STRING_SIZE]; + int ret; + size_t max_len = min_t(size_t, len + 1, STRING_SIZE); + + strlcpy(buffer, buf, max_len); + strlcpy(aim_obj->add_link, buf, max_len); + + ret = split_string(buffer, &mdev, &mdev_ch, &mdev_devnod); + if (ret) + return ret; + + if (mdev_devnod == 0 || *mdev_devnod == 0) { + snprintf(devnod_buf, sizeof(devnod_buf), "%s-%s", mdev, mdev_ch); + mdev_devnod = devnod_buf; + } + + c = get_channel_by_name(mdev, mdev_ch); + if (IS_ERR(c)) + return -ENODEV; + + if (!c->first_aim) + aim_ptr = &c->first_aim; + else if (!c->second_aim) + aim_ptr = &c->second_aim; + else + return -ENOSPC; + + ret = aim_obj->driver->probe_channel(c->iface, c->channel_id, + &c->cfg, &c->kobj, mdev_devnod); + if (ret) + return ret; + *aim_ptr = aim_obj->driver; + return len; +} + +struct most_aim_attribute most_aim_attr_add_link = + __ATTR(add_link, S_IRUGO | S_IWUSR, show_add_link, store_add_link); + +static ssize_t show_remove_link(struct most_aim_obj *aim_obj, + struct most_aim_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%s\n", aim_obj->remove_link); +} + +/** + * store_remove_link - store function for remove_link attribute + * @aim_obj: pointer to AIM object + * @attr: its attributes + * @buf: buffer + * @len: buffer length + * + * Example: + * echo -n -e "mdev0:ch0@ep_81\n" >remove_link + */ +static ssize_t store_remove_link(struct most_aim_obj *aim_obj, + struct most_aim_attribute *attr, + const char *buf, + size_t len) +{ + struct most_c_obj *c; + char buffer[STRING_SIZE]; + char *mdev; + char *mdev_ch; + int ret; + size_t max_len = min_t(size_t, len + 1, STRING_SIZE); + + strlcpy(buffer, buf, max_len); + strlcpy(aim_obj->remove_link, buf, max_len); + ret = split_string(buffer, &mdev, &mdev_ch, NULL); + if (ret) + return ret; + + c = get_channel_by_name(mdev, mdev_ch); + if (IS_ERR(c)) + return -ENODEV; + + if (c->first_aim == aim_obj->driver) + c->first_aim = NULL; + if (c->second_aim == aim_obj->driver) + c->second_aim = NULL; + if (aim_obj->driver->disconnect_channel(c->iface, c->channel_id)) + return -EIO; + return len; +} + +struct most_aim_attribute most_aim_attr_remove_link = + __ATTR(remove_link, S_IRUGO | S_IWUSR, show_remove_link, store_remove_link); + +static struct attribute *most_aim_def_attrs[] = { + &most_aim_attr_add_link.attr, + &most_aim_attr_remove_link.attr, + NULL, +}; + +static struct kobj_type most_aim_ktype = { + .sysfs_ops = &most_aim_sysfs_ops, + .release = most_aim_release, + .default_attrs = most_aim_def_attrs, +}; + +static struct kset *most_aim_kset; + +/** + * create_most_aim_obj - creates an AIM object + * @name: name of the AIM + * + * This creates an AIM object assigns the proper kset and registers + * it with sysfs. + * Returns a pointer to the object or NULL if something went wrong. + */ +static struct most_aim_obj *create_most_aim_obj(const char *name) +{ + struct most_aim_obj *most_aim; + int retval; + + most_aim = kzalloc(sizeof(*most_aim), GFP_KERNEL); + if (!most_aim) + return NULL; + most_aim->kobj.kset = most_aim_kset; + retval = kobject_init_and_add(&most_aim->kobj, &most_aim_ktype, + NULL, "%s", name); + if (retval) { + kobject_put(&most_aim->kobj); + return NULL; + } + kobject_uevent(&most_aim->kobj, KOBJ_ADD); + return most_aim; +} + +/** + * destroy_most_aim_obj - AIM release function + * @p: pointer to AIM object + * + * This decrements the reference counter of the AIM object. If the + * reference count turns zero, its release function will be called. + */ +static void destroy_most_aim_obj(struct most_aim_obj *p) +{ + kobject_put(&p->kobj); +} + + +/* ___ ___ + * ___C O R E___ + */ + +/** + * Instantiation of the MOST bus + */ +struct bus_type most_bus = { + .name = "most", +}; + +/** + * Instantiation of the core driver + */ +struct device_driver mostcore = { + .name = "mostcore", + .bus = &most_bus, +}; + +static inline void trash_mbo(struct mbo *mbo) +{ + unsigned long flags; + struct most_c_obj *c = mbo->context; + + spin_lock_irqsave(&c->fifo_lock, flags); + list_add(&mbo->list, &c->trash_fifo); + spin_unlock_irqrestore(&c->fifo_lock, flags); +} + +static struct mbo *get_hdm_mbo(struct most_c_obj *c) +{ + unsigned long flags; + struct mbo *mbo; + + spin_lock_irqsave(&c->fifo_lock, flags); + if (c->enqueue_halt || list_empty(&c->halt_fifo)) + mbo = NULL; + else + mbo = list_pop_mbo(&c->halt_fifo); + spin_unlock_irqrestore(&c->fifo_lock, flags); + return mbo; +} + +static void nq_hdm_mbo(struct mbo *mbo) +{ + unsigned long flags; + struct most_c_obj *c = mbo->context; + + spin_lock_irqsave(&c->fifo_lock, flags); + list_add_tail(&mbo->list, &c->halt_fifo); + spin_unlock_irqrestore(&c->fifo_lock, flags); + wake_up_interruptible(&c->hdm_fifo_wq); +} + +static int hdm_enqueue_thread(void *data) +{ + struct most_c_obj *c = data; + struct mbo *mbo; + typeof(c->iface->enqueue) enqueue = c->iface->enqueue; + + while (likely(!kthread_should_stop())) { + wait_event_interruptible(c->hdm_fifo_wq, + (mbo = get_hdm_mbo(c)) + || kthread_should_stop()); + + if (unlikely(!mbo)) + continue; + + if (c->cfg.direction == MOST_CH_RX) + mbo->buffer_length = c->cfg.buffer_size; + + if (unlikely(enqueue(mbo->ifp, mbo->hdm_channel_id, mbo))) { + pr_err("hdm enqueue failed\n"); + nq_hdm_mbo(mbo); + c->hdm_enqueue_task = NULL; + return 0; + } + } + + return 0; +} + +static int run_enqueue_thread(struct most_c_obj *c, int channel_id) +{ + struct task_struct *task = + kthread_run(&hdm_enqueue_thread, c, "hdm_fifo_%d", channel_id); + + if (IS_ERR(task)) + return PTR_ERR(task); + + c->hdm_enqueue_task = task; + return 0; +} + +/** + * arm_mbo - recycle MBO for further usage + * @mbo: buffer object + * + * This puts an MBO back to the list to have it ready for up coming + * tx transactions. + * + * In case the MBO belongs to a channel that recently has been + * poisoned, the MBO is scheduled to be trashed. + * Calls the completion handler of an attached AIM. + */ +static void arm_mbo(struct mbo *mbo) +{ + unsigned long flags; + struct most_c_obj *c; + + BUG_ON((!mbo) || (!mbo->context)); + c = mbo->context; + + if (c->is_poisoned) { + trash_mbo(mbo); + return; + } + + spin_lock_irqsave(&c->fifo_lock, flags); + list_add_tail(&mbo->list, &c->fifo); + spin_unlock_irqrestore(&c->fifo_lock, flags); + + if (c->second_aim && c->second_aim->tx_completion) + c->second_aim->tx_completion(c->iface, c->channel_id); + if (c->first_aim && c->first_aim->tx_completion) + c->first_aim->tx_completion(c->iface, c->channel_id); +} + +/** + * arm_mbo_chain - helper function that arms an MBO chain for the HDM + * @c: pointer to interface channel + * @dir: direction of the channel + * @compl: pointer to completion function + * + * This allocates buffer objects including the containing DMA coherent + * buffer and puts them in the fifo. + * Buffers of Rx channels are put in the kthread fifo, hence immediately + * submitted to the HDM. + * + * Returns the number of allocated and enqueued MBOs. + */ +int arm_mbo_chain(struct most_c_obj *c, int dir, void (*compl)(struct mbo *)) +{ + unsigned int i; + int retval; + struct mbo *mbo; + u32 coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len; + + atomic_set(&c->mbo_nq_level, 0); + + for (i = 0; i < c->cfg.num_buffers; i++) { + mbo = kzalloc(sizeof(*mbo), GFP_KERNEL); + if (!mbo) { + pr_info("WARN: Allocation of MBO failed.\n"); + retval = i; + goto _exit; + } + mbo->context = c; + mbo->ifp = c->iface; + mbo->hdm_channel_id = c->channel_id; + mbo->virt_address = dma_alloc_coherent(NULL, + coherent_buf_size, + &mbo->bus_address, + GFP_KERNEL); + if (!mbo->virt_address) { + pr_info("WARN: No DMA coherent buffer.\n"); + retval = i; + goto _error1; + } + mbo->complete = compl; + if (dir == MOST_CH_RX) { + nq_hdm_mbo(mbo); + atomic_inc(&c->mbo_nq_level); + } else { + arm_mbo(mbo); + } + } + return i; + +_error1: + kfree(mbo); +_exit: + return retval; +} + +/** + * most_submit_mbo - submits an MBO to fifo + * @mbo: pointer to the MBO + * + */ +int most_submit_mbo(struct mbo *mbo) +{ + struct most_c_obj *c; + struct most_inst_obj *i; + + if (unlikely((!mbo) || (!mbo->context))) { + pr_err("Bad MBO or missing channel reference\n"); + return -EINVAL; + } + c = mbo->context; + i = c->inst; + + if (unlikely(atomic_read(&i->tainted))) + return -ENODEV; + + nq_hdm_mbo(mbo); + return 0; +} +EXPORT_SYMBOL_GPL(most_submit_mbo); + +/** + * most_write_completion - write completion handler + * @mbo: pointer to MBO + * + * This recycles the MBO for further usage. In case the channel has been + * poisoned, the MBO is scheduled to be trashed. + */ +static void most_write_completion(struct mbo *mbo) +{ + struct most_c_obj *c; + + BUG_ON((!mbo) || (!mbo->context)); + + c = mbo->context; + if (mbo->status == MBO_E_INVAL) + pr_info("WARN: Tx MBO status: invalid\n"); + if (unlikely((c->is_poisoned == true) || (mbo->status == MBO_E_CLOSE))) + trash_mbo(mbo); + else + arm_mbo(mbo); +} + +/** + * get_channel_by_iface - get pointer to channel object + * @iface: pointer to interface instance + * @id: channel ID + * + * This retrieves a pointer to a channel of the given interface and channel ID. + */ +static struct +most_c_obj *get_channel_by_iface(struct most_interface *iface, int id) +{ + struct most_inst_obj *i; + + if (unlikely(!iface)) { + pr_err("Bad interface\n"); + return NULL; + } + if (unlikely((id < 0) || (id >= iface->num_channels))) { + pr_err("Channel index (%d) out of range\n", id); + return NULL; + } + i = iface->priv; + if (unlikely(!i)) { + pr_err("interface is not registered\n"); + return NULL; + } + return i->channel[id]; +} + +/** + * most_get_mbo - get pointer to an MBO of pool + * @iface: pointer to interface instance + * @id: channel ID + * + * This attempts to get a free buffer out of the channel fifo. + * Returns a pointer to MBO on success or NULL otherwise. + */ +struct mbo *most_get_mbo(struct most_interface *iface, int id) +{ + struct mbo *mbo; + struct most_c_obj *c; + unsigned long flags; + + c = get_channel_by_iface(iface, id); + if (unlikely(!c)) + return NULL; + spin_lock_irqsave(&c->fifo_lock, flags); + if (list_empty(&c->fifo)) { + spin_unlock_irqrestore(&c->fifo_lock, flags); + return NULL; + } + mbo = list_pop_mbo(&c->fifo); + spin_unlock_irqrestore(&c->fifo_lock, flags); + mbo->buffer_length = c->cfg.buffer_size; + return mbo; +} +EXPORT_SYMBOL_GPL(most_get_mbo); + + +/** + * most_put_mbo - return buffer to pool + * @mbo: buffer object + */ +void most_put_mbo(struct mbo *mbo) +{ + struct most_c_obj *c; + struct most_inst_obj *i; + + c = mbo->context; + i = c->inst; + + if (unlikely(atomic_read(&i->tainted))) { + mbo->status = MBO_E_CLOSE; + trash_mbo(mbo); + return; + } + if (c->cfg.direction == MOST_CH_TX) { + arm_mbo(mbo); + return; + } + nq_hdm_mbo(mbo); + atomic_inc(&c->mbo_nq_level); +} +EXPORT_SYMBOL_GPL(most_put_mbo); + +/** + * most_read_completion - read completion handler + * @mbo: pointer to MBO + * + * This function is called by the HDM when data has been received from the + * hardware and copied to the buffer of the MBO. + * + * In case the channel has been poisoned it puts the buffer in the trash queue. + * Otherwise, it passes the buffer to an AIM for further processing. + */ +static void most_read_completion(struct mbo *mbo) +{ + struct most_c_obj *c; + + c = mbo->context; + if (unlikely((c->is_poisoned == true) || (mbo->status == MBO_E_CLOSE))) + goto release_mbo; + + if (mbo->status == MBO_E_INVAL) { + nq_hdm_mbo(mbo); + atomic_inc(&c->mbo_nq_level); + return; + } + + if (atomic_sub_and_test(1, &c->mbo_nq_level)) { + pr_info("WARN: rx device out of buffers\n"); + c->is_starving = 1; + } + + if (c->first_aim && c->first_aim->rx_completion && + c->first_aim->rx_completion(mbo) == 0) + return; + if (c->second_aim && c->second_aim->rx_completion && + c->second_aim->rx_completion(mbo) == 0) + return; + pr_info("WARN: no driver linked with this channel\n"); + mbo->status = MBO_E_CLOSE; +release_mbo: + trash_mbo(mbo); +} + +/** + * most_start_channel - prepares a channel for communication + * @iface: pointer to interface instance + * @id: channel ID + * + * This prepares the channel for usage. Cross-checks whether the + * channel's been properly configured. + * + * Returns 0 on success or error code otherwise. + */ +int most_start_channel(struct most_interface *iface, int id) +{ + int num_buffer; + int ret; + struct most_c_obj *c = get_channel_by_iface(iface, id); + + if (unlikely(!c)) + return -EINVAL; + + if (c->is_started) + return -EBUSY; + + if (!try_module_get(iface->mod)) { + pr_info("failed to acquire HDM lock\n"); + return -ENOLCK; + } + modref++; + + c->cfg.extra_len = 0; + if (c->iface->configure(c->iface, c->channel_id, &c->cfg)) { + pr_info("channel configuration failed. Go check settings...\n"); + ret = -EINVAL; + goto error; + } + + init_waitqueue_head(&c->hdm_fifo_wq); + + if (c->cfg.direction == MOST_CH_RX) + num_buffer = arm_mbo_chain(c, c->cfg.direction, + most_read_completion); + else + num_buffer = arm_mbo_chain(c, c->cfg.direction, + most_write_completion); + if (unlikely(0 == num_buffer)) { + pr_info("failed to allocate memory\n"); + ret = -ENOMEM; + goto error; + } + + ret = run_enqueue_thread(c, id); + if (ret) + goto error; + + c->is_started = true; + c->is_starving = 0; + atomic_set(&c->mbo_ref, num_buffer); + return 0; +error: + if (iface->mod) + module_put(iface->mod); + modref--; + return ret; +} +EXPORT_SYMBOL_GPL(most_start_channel); + +/** + * most_stop_channel - stops a running channel + * @iface: pointer to interface instance + * @id: channel ID + */ +int most_stop_channel(struct most_interface *iface, int id) +{ + struct most_c_obj *c; + + if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) { + pr_err("Bad interface or index out of range\n"); + return -EINVAL; + } + c = get_channel_by_iface(iface, id); + if (unlikely(!c)) + return -EINVAL; + + if (!c->is_started) + return 0; + + /* FIXME: we need to know calling AIM to reset only one link */ + c->first_aim = NULL; + c->second_aim = NULL; + /* do not go into recursion calling aim->disconnect_channel */ + + mutex_lock(&c->stop_task_mutex); + if (c->hdm_enqueue_task) + kthread_stop(c->hdm_enqueue_task); + c->hdm_enqueue_task = NULL; + mutex_unlock(&c->stop_task_mutex); + + mutex_lock(&deregister_mutex); + if (atomic_read(&c->inst->tainted)) { + mutex_unlock(&deregister_mutex); + return -ENODEV; + } + mutex_unlock(&deregister_mutex); + + if (iface->mod && modref) { + module_put(iface->mod); + modref--; + } + + c->is_poisoned = true; + if (c->iface->poison_channel(c->iface, c->channel_id)) { + pr_err("Cannot stop channel %d of mdev %s\n", c->channel_id, + c->iface->description); + return -EAGAIN; + } + flush_trash_fifo(c); + flush_channel_fifos(c); + +#ifdef CMPL_INTERRUPTIBLE + if (wait_for_completion_interruptible(&c->cleanup)) { + pr_info("Interrupted while clean up ch %d\n", c->channel_id); + return -EINTR; + } +#else + wait_for_completion(&c->cleanup); +#endif + c->is_poisoned = false; + c->is_started = false; + return 0; +} +EXPORT_SYMBOL_GPL(most_stop_channel); + +/** + * most_register_aim - registers an AIM (driver) with the core + * @aim: instance of AIM to be registered + */ +int most_register_aim(struct most_aim *aim) +{ + struct most_aim_obj *aim_obj; + + if (!aim) { + pr_err("Bad driver\n"); + return -EINVAL; + } + aim_obj = create_most_aim_obj(aim->name); + if (!aim_obj) { + pr_info("failed to alloc driver object\n"); + return -ENOMEM; + } + aim_obj->driver = aim; + aim->context = aim_obj; + pr_info("registered new application interfacing module %s\n", + aim->name); + list_add_tail(&aim_obj->list, &aim_list); + return 0; +} +EXPORT_SYMBOL_GPL(most_register_aim); + +/** + * most_deregister_aim - deregisters an AIM (driver) with the core + * @aim: AIM to be removed + */ +int most_deregister_aim(struct most_aim *aim) +{ + struct most_aim_obj *aim_obj; + struct most_c_obj *c, *tmp; + struct most_inst_obj *i, *i_tmp; + + if (!aim) { + pr_err("Bad driver\n"); + return -EINVAL; + } + + aim_obj = aim->context; + if (!aim_obj) { + pr_info("driver not registered.\n"); + return -EINVAL; + } + list_for_each_entry_safe(i, i_tmp, &instance_list, list) { + list_for_each_entry_safe(c, tmp, &i->channel_list, list) { + if (c->first_aim == aim || c->second_aim == aim) + aim->disconnect_channel( + c->iface, c->channel_id); + if (c->first_aim == aim) + c->first_aim = NULL; + if (c->second_aim == aim) + c->second_aim = NULL; + } + } + list_del(&aim_obj->list); + destroy_most_aim_obj(aim_obj); + pr_info("deregistering application interfacing module %s\n", aim->name); + return 0; +} +EXPORT_SYMBOL_GPL(most_deregister_aim); + +/** + * most_register_interface - registers an interface with core + * @iface: pointer to the instance of the interface description. + * + * Allocates and initializes a new interface instance and all of its channels. + * Returns a pointer to kobject or an error pointer. + */ +struct kobject *most_register_interface(struct most_interface *iface) +{ + unsigned int i; + int id; + char name[STRING_SIZE]; + char channel_name[STRING_SIZE]; + struct most_c_obj *c; + struct most_inst_obj *inst; + + if (!iface || !iface->enqueue || !iface->configure || + !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) { + pr_err("Bad interface or channel overflow\n"); + return ERR_PTR(-EINVAL); + } + + id = ida_simple_get(&mdev_id, 0, 0, GFP_KERNEL); + if (id < 0) { + pr_info("Failed to alloc mdev ID\n"); + return ERR_PTR(id); + } + snprintf(name, STRING_SIZE, "mdev%d", id); + + inst = create_most_inst_obj(name); + if (!inst) { + pr_info("Failed to allocate interface instance\n"); + return ERR_PTR(-ENOMEM); + } + + iface->priv = inst; + INIT_LIST_HEAD(&inst->channel_list); + inst->iface = iface; + inst->dev_id = id; + atomic_set(&inst->tainted, 0); + list_add_tail(&inst->list, &instance_list); + + for (i = 0; i < iface->num_channels; i++) { + const char *name_suffix = iface->channel_vector[i].name_suffix; + + if (!name_suffix) + snprintf(channel_name, STRING_SIZE, "ch%d", i); + else if (name_suffix[0] == '@') + snprintf(channel_name, STRING_SIZE, "ch%d%s", i, + name_suffix); + else + snprintf(channel_name, STRING_SIZE, "%s", name_suffix); + + /* this increments the reference count of this instance */ + c = create_most_c_obj(channel_name, &inst->kobj); + if (!c) + goto free_instance; + inst->channel[i] = c; + c->is_starving = 0; + c->iface = iface; + c->inst = inst; + c->channel_id = i; + c->keep_mbo = false; + c->enqueue_halt = false; + c->is_poisoned = false; + c->is_started = false; + c->cfg.direction = 0; + c->cfg.data_type = 0; + c->cfg.num_buffers = 0; + c->cfg.buffer_size = 0; + c->cfg.subbuffer_size = 0; + c->cfg.packets_per_xact = 0; + spin_lock_init(&c->fifo_lock); + INIT_LIST_HEAD(&c->fifo); + INIT_LIST_HEAD(&c->trash_fifo); + INIT_LIST_HEAD(&c->halt_fifo); + init_completion(&c->cleanup); + atomic_set(&c->mbo_ref, 0); + mutex_init(&c->stop_task_mutex); + list_add_tail(&c->list, &inst->channel_list); + } + pr_info("registered new MOST device mdev%d (%s)\n", + inst->dev_id, iface->description); + return &inst->kobj; + +free_instance: + pr_info("Failed allocate channel(s)\n"); + list_del(&inst->list); + destroy_most_inst_obj(inst); + return ERR_PTR(-ENOMEM); +} +EXPORT_SYMBOL_GPL(most_register_interface); + +/** + * most_deregister_interface - deregisters an interface with core + * @iface: pointer to the interface instance description. + * + * Before removing an interface instance from the list, all running + * channels are stopped and poisoned. + */ +void most_deregister_interface(struct most_interface *iface) +{ + struct most_inst_obj *i = iface->priv; + struct most_c_obj *c; + + mutex_lock(&deregister_mutex); + if (unlikely(!i)) { + pr_info("Bad Interface\n"); + mutex_unlock(&deregister_mutex); + return; + } + pr_info("deregistering MOST device %s (%s)\n", i->kobj.name, + iface->description); + + atomic_set(&i->tainted, 1); + mutex_unlock(&deregister_mutex); + + while (modref) { + if (iface->mod && modref) + module_put(iface->mod); + modref--; + } + + list_for_each_entry(c, &i->channel_list, list) { + if (!c->is_started) + continue; + + mutex_lock(&c->stop_task_mutex); + if (c->hdm_enqueue_task) + kthread_stop(c->hdm_enqueue_task); + c->hdm_enqueue_task = NULL; + mutex_unlock(&c->stop_task_mutex); + + if (iface->poison_channel(iface, c->channel_id)) + pr_err("Can't poison channel %d\n", c->channel_id); + } + ida_simple_remove(&mdev_id, i->dev_id); + list_del(&i->list); + destroy_most_inst_obj(i); +} +EXPORT_SYMBOL_GPL(most_deregister_interface); + +/** + * most_stop_enqueue - prevents core from enqueueing MBOs + * @iface: pointer to interface + * @id: channel id + * + * This is called by an HDM that _cannot_ attend to its duties and + * is imminent to get run over by the core. The core is not going to + * enqueue any further packets unless the flagging HDM calls + * most_resume enqueue(). + */ +void most_stop_enqueue(struct most_interface *iface, int id) +{ + struct most_c_obj *c = get_channel_by_iface(iface, id); + + if (likely(c)) + c->enqueue_halt = true; +} +EXPORT_SYMBOL_GPL(most_stop_enqueue); + +/** + * most_resume_enqueue - allow core to enqueue MBOs again + * @iface: pointer to interface + * @id: channel id + * + * This clears the enqueue halt flag and enqueues all MBOs currently + * sitting in the wait fifo. + */ +void most_resume_enqueue(struct most_interface *iface, int id) +{ + struct most_c_obj *c = get_channel_by_iface(iface, id); + + if (unlikely(!c)) + return; + c->enqueue_halt = false; + + wake_up_interruptible(&c->hdm_fifo_wq); +} +EXPORT_SYMBOL_GPL(most_resume_enqueue); + +static int __init most_init(void) +{ + pr_info("init()\n"); + INIT_LIST_HEAD(&instance_list); + INIT_LIST_HEAD(&aim_list); + mutex_init(&deregister_mutex); + ida_init(&mdev_id); + + if (bus_register(&most_bus)) { + pr_info("Cannot register most bus\n"); + goto exit; + } + + most_class = class_create(THIS_MODULE, "most"); + if (IS_ERR(most_class)) { + pr_info("No udev support.\n"); + goto exit_bus; + } + if (driver_register(&mostcore)) { + pr_info("Cannot register core driver\n"); + goto exit_class; + } + + class_glue_dir = + device_create(most_class, NULL, 0, NULL, "mostcore"); + if (!class_glue_dir) + goto exit_driver; + + most_aim_kset = + kset_create_and_add("aims", NULL, &class_glue_dir->kobj); + if (!most_aim_kset) + goto exit_class_container; + + most_inst_kset = + kset_create_and_add("devices", NULL, &class_glue_dir->kobj); + if (!most_inst_kset) + goto exit_driver_kset; + + return 0; + +exit_driver_kset: + kset_unregister(most_aim_kset); +exit_class_container: + device_destroy(most_class, 0); +exit_driver: + driver_unregister(&mostcore); +exit_class: + class_destroy(most_class); +exit_bus: + bus_unregister(&most_bus); +exit: + return -ENOMEM; +} + +static void __exit most_exit(void) +{ + struct most_inst_obj *i, *i_tmp; + struct most_aim_obj *d, *d_tmp; + + pr_info("exit core module\n"); + list_for_each_entry_safe(d, d_tmp, &aim_list, list) { + destroy_most_aim_obj(d); + } + + list_for_each_entry_safe(i, i_tmp, &instance_list, list) { + list_del(&i->list); + destroy_most_inst_obj(i); + } + kset_unregister(most_inst_kset); + kset_unregister(most_aim_kset); + device_destroy(most_class, 0); + driver_unregister(&mostcore); + class_destroy(most_class); + bus_unregister(&most_bus); + ida_destroy(&mdev_id); +} + +module_init(most_init); +module_exit(most_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>"); +MODULE_DESCRIPTION("Core module of stacked MOST Linux driver"); diff --git a/drivers/staging/most/mostcore/mostcore.h b/drivers/staging/most/mostcore/mostcore.h new file mode 100644 index 000000000000..299c7d5aa73a --- /dev/null +++ b/drivers/staging/most/mostcore/mostcore.h @@ -0,0 +1,316 @@ +/* + * mostcore.h - Interface between MostCore, + * Hardware Dependent Module (HDM) and Application Interface Module (AIM). + * + * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This file is licensed under GPLv2. + */ + +/* + * Authors: + * Andrey Shvetsov <andrey.shvetsov@k2l.de> + * Christian Gromm <christian.gromm@microchip.com> + * Sebastian Graf + */ + +#ifndef __MOST_CORE_H__ +#define __MOST_CORE_H__ + +#include <linux/types.h> + +struct kobject; +struct module; + +/** + * Interface type + */ +enum most_interface_type { + ITYPE_LOOPBACK = 1, + ITYPE_I2C, + ITYPE_I2S, + ITYPE_TSI, + ITYPE_HBI, + ITYPE_MEDIALB_DIM, + ITYPE_MEDIALB_DIM2, + ITYPE_USB, + ITYPE_PCIE +}; + +/** + * Channel direction. + */ +enum most_channel_direction { + MOST_CH_RX = 1 << 0, + MOST_CH_TX = 1 << 1, +}; + +/** + * Channel data type. + */ +enum most_channel_data_type { + MOST_CH_CONTROL = 1 << 0, + MOST_CH_ASYNC = 1 << 1, + MOST_CH_ISOC_AVP = 1 << 2, + MOST_CH_SYNC = 1 << 5, +}; + + +enum mbo_status_flags { + /* MBO was processed successfully (data was send or received )*/ + MBO_SUCCESS = 0, + /* The MBO contains wrong or missing information. */ + MBO_E_INVAL, + /* MBO was completed as HDM Channel will be closed */ + MBO_E_CLOSE, +}; + +/** + * struct most_channel_capability - Channel capability + * @direction: Supported channel directions. + * The value is bitwise OR-combination of the values from the + * enumeration most_channel_direction. Zero is allowed value and means + * "channel may not be used". + * @data_type: Supported channel data types. + * The value is bitwise OR-combination of the values from the + * enumeration most_channel_data_type. Zero is allowed value and means + * "channel may not be used". + * @num_buffer_packet: Maximum number of buffers supported by this channel + * for packet data types (Async,Control,QoS) + * @buffer_size_packet: Maximum buffer size supported by this channel + * for packet data types (Async,Control,QoS) + * @num_buffer_streaming: Maximum number of buffers supported by this channel + * for streaming data types (Sync,AV Packetized) + * @buffer_size_streaming: Maximum buffer size supported by this channel + * for streaming data types (Sync,AV Packetized) + * @name_suffix: Optional suffix providean by an HDM that is attached to the + * regular channel name. + * + * Describes the capabilities of a MostCore channel like supported Data Types + * and directions. This information is provided by an HDM for the MostCore. + * + * The Core creates read only sysfs attribute files in + * /sys/devices/virtual/most/mostcore/devices/mdev-#/mdev#-ch#/ with the + * following attributes: + * -available_directions + * -available_datatypes + * -number_of_packet_buffers + * -number_of_stream_buffers + * -size_of_packet_buffer + * -size_of_stream_buffer + * where content of each file is a string with all supported properties of this + * very channel attribute. + */ +struct most_channel_capability { + u16 direction; + u16 data_type; + u16 num_buffers_packet; + u16 buffer_size_packet; + u16 num_buffers_streaming; + u16 buffer_size_streaming; + char *name_suffix; +}; + +/** + * struct most_channel_config - stores channel configuration + * @direction: direction of the channel + * @data_type: data type travelling over this channel + * @num_buffers: number of buffers + * @buffer_size: size of a buffer for AIM. + * Buffer size may be cutted down by HDM in a configure callback + * to match to a given interface and channel type. + * @extra_len: additional buffer space for internal HDM purposes like padding. + * May be set by HDM in a configure callback if needed. + * @subbuffer_size: size of a subbuffer + * @packets_per_xact: number of MOST frames that are packet inside one USB + * packet. This is USB specific + * + * Describes the configuration for a MostCore channel. This information is + * provided from the MostCore to a HDM (like the Medusa PCIe Interface) as a + * parameter of the "configure" function call. + */ +struct most_channel_config { + enum most_channel_direction direction; + enum most_channel_data_type data_type; + u16 num_buffers; + u16 buffer_size; + u16 extra_len; + u16 subbuffer_size; + u16 packets_per_xact; +}; + +/* + * struct mbo - MOST Buffer Object. + * @context: context for core completion handler + * @priv: private data for HDM + * + * public: documented fields that are used for the communications + * between MostCore and HDMs + * + * @list: list head for use by the mbo's current owner + * @ifp: (in) associated interface instance + * @hdm_channel_id: (in) HDM channel instance + * @virt_address: (in) kernel virtual address of the buffer + * @bus_address: (in) bus address of the buffer + * @buffer_length: (in) buffer payload length + * @processed_length: (out) processed length + * @status: (out) transfer status + * @complete: (in) completion routine + * + * The MostCore allocates and initializes the MBO. + * + * The HDM receives MBO for transfer from MostCore with the call to enqueue(). + * The HDM copies the data to- or from the buffer depending on configured + * channel direction, set "processed_length" and "status" and completes + * the transfer procedure by calling the completion routine. + * + * At the end the MostCore deallocates the MBO or recycles it for further + * transfers for the same or different HDM. + * + * Directions of usage: + * The core driver should never access any MBO fields (even if marked + * as "public") while the MBO is owned by an HDM. The ownership starts with + * the call of enqueue() and ends with the call of its complete() routine. + * + * II. + * Every HDM attached to the core driver _must_ ensure that it returns any MBO + * it owns (due to a previous call to enqueue() by the core driver) before it + * de-registers an interface or gets unloaded from the kernel. If this direction + * is violated memory leaks will occur, since the core driver does _not_ track + * MBOs it is currently not in control of. + * + */ +struct mbo { + void *context; + void *priv; + struct list_head list; + struct most_interface *ifp; + u16 hdm_channel_id; + void *virt_address; + dma_addr_t bus_address; + u16 buffer_length; + u16 processed_length; + enum mbo_status_flags status; + void (*complete)(struct mbo *); +}; + +/** + * Interface instance description. + * + * Describes one instance of an interface like Medusa PCIe or Vantage USB. + * This structure is allocated and initialized in the HDM. MostCore may not + * modify this structure. + * + * @interface Interface type. \sa most_interface_type. + * @description PRELIMINARY. + * Unique description of the device instance from point of view of the + * interface in free text form (ASCII). + * It may be a hexadecimal presentation of the memory address for the MediaLB + * IP or USB device ID with USB properties for USB interface, etc. + * @num_channels Number of channels and size of the channel_vector. + * @channel_vector Properties of the channels. + * Array index represents channel ID by the driver. + * @configure Callback to change data type for the channel of the + * interface instance. May be zero if the instance of the interface is not + * configurable. Parameter channel_config describes direction and data + * type for the channel, configured by the higher level. The content of + * @enqueue Delivers MBO to the HDM for processing. + * After HDM completes Rx- or Tx- operation the processed MBO shall + * be returned back to the MostCore using completion routine. + * The reason to get the MBO delivered from the MostCore after the channel + * is poisoned is the re-opening of the channel by the application. + * In this case the HDM shall hold MBOs and service the channel as usual. + * The HDM must be able to hold at least one MBO for each channel. + * The callback returns a negative value on error, otherwise 0. + * @poison_channel Informs HDM about closing the channel. The HDM shall + * cancel all transfers and synchronously or asynchronously return + * all enqueued for this channel MBOs using the completion routine. + * The callback returns a negative value on error, otherwise 0. + * @request_netinfo: triggers retrieving of network info from the HDM by + * means of "Message exchange over MDP/MEP" + * @priv Private field used by mostcore to store context information. + */ +struct most_interface { + struct module *mod; + enum most_interface_type interface; + const char *description; + int num_channels; + struct most_channel_capability *channel_vector; + int (*configure)(struct most_interface *iface, int channel_idx, + struct most_channel_config *channel_config); + int (*enqueue)(struct most_interface *iface, int channel_idx, + struct mbo *mbo); + int (*poison_channel)(struct most_interface *iface, int channel_idx); + void (*request_netinfo)(struct most_interface *iface, int channel_idx); + void *priv; +}; + +/** + * struct most_aim - identifies MOST device driver to mostcore + * @name: Driver name + * @probe_channel: function for core to notify driver about channel connection + * @disconnect_channel: notification that a certain channel isn't available anymore + * @rx_completion: completion handler for received packets + * @tx_completion: completion handler for transmitted packets + * @context: context pointer to be used by mostcore + */ +struct most_aim { + const char *name; + int (*probe_channel)(struct most_interface *iface, int channel_idx, + struct most_channel_config *cfg, + struct kobject *parent, char *name); + int (*disconnect_channel)(struct most_interface *iface, + int channel_idx); + int (*rx_completion)(struct mbo *mbo); + int (*tx_completion)(struct most_interface *iface, int channel_idx); + void *context; +}; + +/** + * most_register_interface - Registers instance of the interface. + * @iface: Pointer to the interface instance description. + * + * Returns a pointer to the kobject of the generated instance. + * + * Note: HDM has to ensure that any reference held on the kobj is + * released before deregistering the interface. + */ +struct kobject *most_register_interface(struct most_interface *iface); + +/** + * Deregisters instance of the interface. + * @intf_instance Pointer to the interface instance description. + */ +void most_deregister_interface(struct most_interface *iface); +int most_submit_mbo(struct mbo *mbo); + +/** + * most_stop_enqueue - prevents core from enqueing MBOs + * @iface: pointer to interface + * @channel_idx: channel index + */ +void most_stop_enqueue(struct most_interface *iface, int channel_idx); + +/** + * most_resume_enqueue - allow core to enqueue MBOs again + * @iface: pointer to interface + * @channel_idx: channel index + * + * This clears the enqueue halt flag and enqueues all MBOs currently + * in wait fifo. + */ +void most_resume_enqueue(struct most_interface *iface, int channel_idx); +int most_register_aim(struct most_aim *aim); +int most_deregister_aim(struct most_aim *aim); +struct mbo *most_get_mbo(struct most_interface *iface, int channel_idx); +void most_put_mbo(struct mbo *mbo); +int most_start_channel(struct most_interface *iface, int channel_idx); +int most_stop_channel(struct most_interface *iface, int channel_idx); + + +#endif /* MOST_CORE_H_ */ diff --git a/drivers/staging/netlogic/platform_net.c b/drivers/staging/netlogic/platform_net.c index 77c3c3522afa..e914147d7379 100644 --- a/drivers/staging/netlogic/platform_net.c +++ b/drivers/staging/netlogic/platform_net.c @@ -163,7 +163,7 @@ static void xls_gmac_init(void) switch (nlm_prom_info.board_major_version) { case 12: /* first block RGMII or XAUI, use RGMII */ - ndata0.phy_interface = PHY_INTERFACE_MODE_RGMII, + ndata0.phy_interface = PHY_INTERFACE_MODE_RGMII; ndata0.tx_stnid[0] = FMN_STNID_GMAC0_TX0; ndata0.phy_addr[0] = 0; diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index beb7aac9c289..51dcb611702f 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c @@ -118,9 +118,10 @@ static void cvm_oct_rgmii_poll(struct net_device *dev) } /* Since the 10Mbps preamble workaround is allowed we need to enable - preamble checking, FCS stripping, and clear error bits on - every speed change. If errors occur during 10Mbps operation - the above code will change this stuff */ + * preamble checking, FCS stripping, and clear error bits on + * every speed change. If errors occur during 10Mbps operation + * the above code will change this stuff + */ cvm_oct_set_hw_preamble(priv, true); if (priv->phydev == NULL) { diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index f9dba23a3759..0718b35f7335 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -157,6 +157,7 @@ static void cvm_oct_configure_common_hw(void) #ifdef __LITTLE_ENDIAN { union cvmx_ipd_ctl_status ipd_ctl_status; + ipd_ctl_status.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS); ipd_ctl_status.s.pkt_lend = 1; ipd_ctl_status.s.wqe_lend = 1; diff --git a/drivers/staging/ozwpan/Kconfig b/drivers/staging/ozwpan/Kconfig deleted file mode 100644 index 7904caec546a..000000000000 --- a/drivers/staging/ozwpan/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -config USB_WPAN_HCD - tristate "USB over WiFi Host Controller" - depends on USB && NET - help - A driver for USB Host Controllers that are compatible with - Ozmo Devices USB over WiFi technology. - - To compile this driver a module, choose M here: the module - will be called "ozwpan". diff --git a/drivers/staging/ozwpan/Makefile b/drivers/staging/ozwpan/Makefile deleted file mode 100644 index 29529c1a8e3c..000000000000 --- a/drivers/staging/ozwpan/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# ----------------------------------------------------------------------------- -# Copyright (c) 2011 Ozmo Inc -# Released under the GNU General Public License Version 2 (GPLv2). -# ----------------------------------------------------------------------------- - -obj-$(CONFIG_USB_WPAN_HCD) += ozwpan.o -ozwpan-y := \ - ozmain.o \ - ozpd.o \ - ozusbsvc.o \ - ozusbsvc1.o \ - ozhcd.o \ - ozeltbuf.o \ - ozproto.o \ - ozcdev.o \ - ozurbparanoia.o diff --git a/drivers/staging/ozwpan/README b/drivers/staging/ozwpan/README deleted file mode 100644 index 7c055ec99544..000000000000 --- a/drivers/staging/ozwpan/README +++ /dev/null @@ -1,25 +0,0 @@ -OZWPAN USB Host Controller Driver ---------------------------------- -This driver is a USB HCD driver that does not have an associated a physical -device but instead uses Wi-Fi to communicate with the wireless peripheral. -The USB requests are converted into a layer 2 network protocol and transmitted -on the network using an ethertype (0x892e) regestered to Ozmo Device Inc. -This driver is compatible with existing wireless devices that use Ozmo Devices -technology. - -To operate the driver must be bound to a suitable network interface. This can -be done when the module is loaded (specifying the name of the network interface -as a parameter - e.g. 'insmod ozwpan g_net_dev=go0') or can be bound after -loading using an ioctl call. See the ozappif.h file and the ioctls -OZ_IOCTL_ADD_BINDING and OZ_IOCTL_REMOVE_BINDING. - -The devices connect to the host use Wi-Fi Direct so a network card that supports -Wi-Fi direct is required. A recent version (0.8.x or later) version of the -wpa_supplicant can be used to setup the network interface to create a persistent -autonomous group (for older pre-WFD peripherals) or put in a listen state to -allow group negotiation to occur for more recent devices that support WFD. - -The protocol used over the network does not directly mimic the USB bus -transactions as this would be rather busy and inefficient. Instead the chapter 9 -requests are converted into a request/response pair of messages. (See -ozprotocol.h for data structures used in the protocol). diff --git a/drivers/staging/ozwpan/TODO b/drivers/staging/ozwpan/TODO deleted file mode 100644 index f32c1c0bc875..000000000000 --- a/drivers/staging/ozwpan/TODO +++ /dev/null @@ -1,14 +0,0 @@ -TODO: - - Convert event tracing code to in-kernel tracing infrastructure - - Check for remaining ioctl & check if that can be converted into - sysfs entries - - Convert debug prints to appropriate dev_debug or something better - - Modify Kconfig to add CONFIG option for enabling/disabling event - tracing. - - check USB HCD implementation is complete and correct. - - code review by USB developer community. - - testing with as many devices as possible. - -Please send any patches for this driver to -Shigekatsu Tateno <shigekatsu.tateno@atmel.com> -and Greg Kroah-Hartman <gregkh@linuxfoundation.org>. diff --git a/drivers/staging/ozwpan/ozappif.h b/drivers/staging/ozwpan/ozappif.h deleted file mode 100644 index ea1b271fdcda..000000000000 --- a/drivers/staging/ozwpan/ozappif.h +++ /dev/null @@ -1,36 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * ----------------------------------------------------------------------------- - */ -#ifndef _OZAPPIF_H -#define _OZAPPIF_H - -#define OZ_IOCTL_MAGIC 0xf4 - -struct oz_mac_addr { - __u8 a[6]; -}; - -#define OZ_MAX_PDS 8 - -struct oz_pd_list { - __u32 count; - struct oz_mac_addr addr[OZ_MAX_PDS]; -}; - -#define OZ_MAX_BINDING_LEN 32 - -struct oz_binding_info { - char name[OZ_MAX_BINDING_LEN]; -}; - -#define OZ_IOCTL_GET_PD_LIST _IOR(OZ_IOCTL_MAGIC, 0, struct oz_pd_list) -#define OZ_IOCTL_SET_ACTIVE_PD _IOW(OZ_IOCTL_MAGIC, 1, struct oz_mac_addr) -#define OZ_IOCTL_GET_ACTIVE_PD _IOR(OZ_IOCTL_MAGIC, 2, struct oz_mac_addr) -#define OZ_IOCTL_ADD_BINDING _IOW(OZ_IOCTL_MAGIC, 3, struct oz_binding_info) -#define OZ_IOCTL_REMOVE_BINDING _IOW(OZ_IOCTL_MAGIC, 4, struct oz_binding_info) -#define OZ_IOCTL_MAX 5 - - -#endif /* _OZAPPIF_H */ diff --git a/drivers/staging/ozwpan/ozcdev.c b/drivers/staging/ozwpan/ozcdev.c deleted file mode 100644 index da0e1fd50f26..000000000000 --- a/drivers/staging/ozwpan/ozcdev.c +++ /dev/null @@ -1,554 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * ----------------------------------------------------------------------------- - */ -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/cdev.h> -#include <linux/uaccess.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/poll.h> -#include <linux/sched.h> -#include "ozdbg.h" -#include "ozprotocol.h" -#include "ozappif.h" -#include "ozeltbuf.h" -#include "ozpd.h" -#include "ozproto.h" -#include "ozcdev.h" - -#define OZ_RD_BUF_SZ 256 -struct oz_cdev { - dev_t devnum; - struct cdev cdev; - wait_queue_head_t rdq; - spinlock_t lock; - u8 active_addr[ETH_ALEN]; - struct oz_pd *active_pd; -}; - -/* Per PD context for the serial service stored in the PD. */ -struct oz_serial_ctx { - atomic_t ref_count; - u8 tx_seq_num; - u8 rx_seq_num; - u8 rd_buf[OZ_RD_BUF_SZ]; - int rd_in; - int rd_out; -}; - -static struct oz_cdev g_cdev; -static struct class *g_oz_class; - -/* - * Context: process and softirq - */ -static struct oz_serial_ctx *oz_cdev_claim_ctx(struct oz_pd *pd) -{ - struct oz_serial_ctx *ctx; - - spin_lock_bh(&pd->app_lock[OZ_APPID_SERIAL]); - ctx = (struct oz_serial_ctx *) pd->app_ctx[OZ_APPID_SERIAL]; - if (ctx) - atomic_inc(&ctx->ref_count); - spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL]); - return ctx; -} - -/* - * Context: softirq or process - */ -static void oz_cdev_release_ctx(struct oz_serial_ctx *ctx) -{ - if (atomic_dec_and_test(&ctx->ref_count)) { - oz_dbg(ON, "Dealloc serial context\n"); - kfree(ctx); - } -} - -/* - * Context: process - */ -static int oz_cdev_open(struct inode *inode, struct file *filp) -{ - struct oz_cdev *dev = container_of(inode->i_cdev, struct oz_cdev, cdev); - - oz_dbg(ON, "major = %d minor = %d\n", imajor(inode), iminor(inode)); - - filp->private_data = dev; - return 0; -} - -/* - * Context: process - */ -static int oz_cdev_release(struct inode *inode, struct file *filp) -{ - return 0; -} - -/* - * Context: process - */ -static ssize_t oz_cdev_read(struct file *filp, char __user *buf, size_t count, - loff_t *fpos) -{ - int n; - int ix; - - struct oz_pd *pd; - struct oz_serial_ctx *ctx; - - spin_lock_bh(&g_cdev.lock); - pd = g_cdev.active_pd; - if (pd) - oz_pd_get(pd); - spin_unlock_bh(&g_cdev.lock); - if (pd == NULL) - return -1; - ctx = oz_cdev_claim_ctx(pd); - if (ctx == NULL) - goto out2; - n = ctx->rd_in - ctx->rd_out; - if (n < 0) - n += OZ_RD_BUF_SZ; - if (count > n) - count = n; - ix = ctx->rd_out; - n = OZ_RD_BUF_SZ - ix; - if (n > count) - n = count; - if (copy_to_user(buf, &ctx->rd_buf[ix], n)) { - count = 0; - goto out1; - } - ix += n; - if (ix == OZ_RD_BUF_SZ) - ix = 0; - if (n < count) { - if (copy_to_user(&buf[n], ctx->rd_buf, count-n)) { - count = 0; - goto out1; - } - ix = count-n; - } - ctx->rd_out = ix; -out1: - oz_cdev_release_ctx(ctx); -out2: - oz_pd_put(pd); - return count; -} - -/* - * Context: process - */ -static ssize_t oz_cdev_write(struct file *filp, const char __user *buf, - size_t count, loff_t *fpos) -{ - struct oz_pd *pd; - struct oz_elt_buf *eb; - struct oz_elt_info *ei; - struct oz_elt *elt; - struct oz_app_hdr *app_hdr; - struct oz_serial_ctx *ctx; - - if (count > sizeof(ei->data) - sizeof(*elt) - sizeof(*app_hdr)) - return -EINVAL; - - spin_lock_bh(&g_cdev.lock); - pd = g_cdev.active_pd; - if (pd) - oz_pd_get(pd); - spin_unlock_bh(&g_cdev.lock); - if (pd == NULL) - return -ENXIO; - if (!(pd->state & OZ_PD_S_CONNECTED)) - return -EAGAIN; - eb = &pd->elt_buff; - ei = oz_elt_info_alloc(eb); - if (ei == NULL) { - count = 0; - goto out; - } - elt = (struct oz_elt *)ei->data; - app_hdr = (struct oz_app_hdr *)(elt+1); - elt->length = sizeof(struct oz_app_hdr) + count; - elt->type = OZ_ELT_APP_DATA; - ei->app_id = OZ_APPID_SERIAL; - ei->length = elt->length + sizeof(struct oz_elt); - app_hdr->app_id = OZ_APPID_SERIAL; - if (copy_from_user(app_hdr+1, buf, count)) - goto out; - spin_lock_bh(&pd->app_lock[OZ_APPID_USB]); - ctx = (struct oz_serial_ctx *) pd->app_ctx[OZ_APPID_SERIAL]; - if (ctx) { - app_hdr->elt_seq_num = ctx->tx_seq_num++; - if (ctx->tx_seq_num == 0) - ctx->tx_seq_num = 1; - spin_lock(&eb->lock); - if (oz_queue_elt_info(eb, 0, 0, ei) == 0) - ei = NULL; - spin_unlock(&eb->lock); - } - spin_unlock_bh(&pd->app_lock[OZ_APPID_USB]); -out: - if (ei) { - count = 0; - spin_lock_bh(&eb->lock); - oz_elt_info_free(eb, ei); - spin_unlock_bh(&eb->lock); - } - oz_pd_put(pd); - return count; -} - -/* - * Context: process - */ -static int oz_set_active_pd(const u8 *addr) -{ - int rc = 0; - struct oz_pd *pd; - struct oz_pd *old_pd; - - pd = oz_pd_find(addr); - if (pd) { - spin_lock_bh(&g_cdev.lock); - ether_addr_copy(g_cdev.active_addr, addr); - old_pd = g_cdev.active_pd; - g_cdev.active_pd = pd; - spin_unlock_bh(&g_cdev.lock); - if (old_pd) - oz_pd_put(old_pd); - } else { - if (is_zero_ether_addr(addr)) { - spin_lock_bh(&g_cdev.lock); - pd = g_cdev.active_pd; - g_cdev.active_pd = NULL; - memset(g_cdev.active_addr, 0, - sizeof(g_cdev.active_addr)); - spin_unlock_bh(&g_cdev.lock); - if (pd) - oz_pd_put(pd); - } else { - rc = -1; - } - } - return rc; -} - -/* - * Context: process - */ -static long oz_cdev_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - int rc = 0; - - if (_IOC_TYPE(cmd) != OZ_IOCTL_MAGIC) - return -ENOTTY; - if (_IOC_NR(cmd) > OZ_IOCTL_MAX) - return -ENOTTY; - if (_IOC_DIR(cmd) & _IOC_READ) - rc = !access_ok(VERIFY_WRITE, (void __user *)arg, - _IOC_SIZE(cmd)); - else if (_IOC_DIR(cmd) & _IOC_WRITE) - rc = !access_ok(VERIFY_READ, (void __user *)arg, - _IOC_SIZE(cmd)); - if (rc) - return -EFAULT; - switch (cmd) { - case OZ_IOCTL_GET_PD_LIST: { - struct oz_pd_list list; - - oz_dbg(ON, "OZ_IOCTL_GET_PD_LIST\n"); - memset(&list, 0, sizeof(list)); - list.count = oz_get_pd_list(list.addr, OZ_MAX_PDS); - if (copy_to_user((void __user *)arg, &list, - sizeof(list))) - return -EFAULT; - } - break; - case OZ_IOCTL_SET_ACTIVE_PD: { - u8 addr[ETH_ALEN]; - - oz_dbg(ON, "OZ_IOCTL_SET_ACTIVE_PD\n"); - if (copy_from_user(addr, (void __user *)arg, ETH_ALEN)) - return -EFAULT; - rc = oz_set_active_pd(addr); - } - break; - case OZ_IOCTL_GET_ACTIVE_PD: { - u8 addr[ETH_ALEN]; - - oz_dbg(ON, "OZ_IOCTL_GET_ACTIVE_PD\n"); - spin_lock_bh(&g_cdev.lock); - ether_addr_copy(addr, g_cdev.active_addr); - spin_unlock_bh(&g_cdev.lock); - if (copy_to_user((void __user *)arg, addr, ETH_ALEN)) - return -EFAULT; - } - break; - case OZ_IOCTL_ADD_BINDING: - case OZ_IOCTL_REMOVE_BINDING: { - struct oz_binding_info b; - - if (copy_from_user(&b, (void __user *)arg, - sizeof(struct oz_binding_info))) { - return -EFAULT; - } - /* Make sure name is null terminated. */ - b.name[OZ_MAX_BINDING_LEN-1] = 0; - if (cmd == OZ_IOCTL_ADD_BINDING) - oz_binding_add(b.name); - else - oz_binding_remove(b.name); - } - break; - } - return rc; -} - -/* - * Context: process - */ -static unsigned int oz_cdev_poll(struct file *filp, poll_table *wait) -{ - unsigned int ret = 0; - struct oz_cdev *dev = filp->private_data; - - oz_dbg(ON, "Poll called wait = %p\n", wait); - spin_lock_bh(&dev->lock); - if (dev->active_pd) { - struct oz_serial_ctx *ctx = oz_cdev_claim_ctx(dev->active_pd); - - if (ctx) { - if (ctx->rd_in != ctx->rd_out) - ret |= POLLIN | POLLRDNORM; - oz_cdev_release_ctx(ctx); - } - } - spin_unlock_bh(&dev->lock); - if (wait) - poll_wait(filp, &dev->rdq, wait); - return ret; -} - -/* - */ -static const struct file_operations oz_fops = { - .owner = THIS_MODULE, - .open = oz_cdev_open, - .release = oz_cdev_release, - .read = oz_cdev_read, - .write = oz_cdev_write, - .unlocked_ioctl = oz_cdev_ioctl, - .poll = oz_cdev_poll -}; - -/* - * Context: process - */ -int oz_cdev_register(void) -{ - int err; - struct device *dev; - - memset(&g_cdev, 0, sizeof(g_cdev)); - err = alloc_chrdev_region(&g_cdev.devnum, 0, 1, "ozwpan"); - if (err < 0) - return err; - oz_dbg(ON, "Alloc dev number %d:%d\n", - MAJOR(g_cdev.devnum), MINOR(g_cdev.devnum)); - cdev_init(&g_cdev.cdev, &oz_fops); - g_cdev.cdev.owner = THIS_MODULE; - spin_lock_init(&g_cdev.lock); - init_waitqueue_head(&g_cdev.rdq); - err = cdev_add(&g_cdev.cdev, g_cdev.devnum, 1); - if (err < 0) { - oz_dbg(ON, "Failed to add cdev\n"); - goto unregister; - } - g_oz_class = class_create(THIS_MODULE, "ozmo_wpan"); - if (IS_ERR(g_oz_class)) { - oz_dbg(ON, "Failed to register ozmo_wpan class\n"); - err = PTR_ERR(g_oz_class); - goto delete; - } - dev = device_create(g_oz_class, NULL, g_cdev.devnum, NULL, "ozwpan"); - if (IS_ERR(dev)) { - oz_dbg(ON, "Failed to create sysfs entry for cdev\n"); - err = PTR_ERR(dev); - goto delete; - } - return 0; - -delete: - cdev_del(&g_cdev.cdev); -unregister: - unregister_chrdev_region(g_cdev.devnum, 1); - return err; -} - -/* - * Context: process - */ -int oz_cdev_deregister(void) -{ - cdev_del(&g_cdev.cdev); - unregister_chrdev_region(g_cdev.devnum, 1); - if (g_oz_class) { - device_destroy(g_oz_class, g_cdev.devnum); - class_destroy(g_oz_class); - } - return 0; -} - -/* - * Context: process - */ -int oz_cdev_init(void) -{ - oz_app_enable(OZ_APPID_SERIAL, 1); - return 0; -} - -/* - * Context: process - */ -void oz_cdev_term(void) -{ - oz_app_enable(OZ_APPID_SERIAL, 0); -} - -/* - * Context: softirq-serialized - */ -int oz_cdev_start(struct oz_pd *pd, int resume) -{ - struct oz_serial_ctx *ctx; - struct oz_serial_ctx *old_ctx; - - if (resume) { - oz_dbg(ON, "Serial service resumed\n"); - return 0; - } - ctx = kzalloc(sizeof(struct oz_serial_ctx), GFP_ATOMIC); - if (ctx == NULL) - return -ENOMEM; - atomic_set(&ctx->ref_count, 1); - ctx->tx_seq_num = 1; - spin_lock_bh(&pd->app_lock[OZ_APPID_SERIAL]); - old_ctx = pd->app_ctx[OZ_APPID_SERIAL]; - if (old_ctx) { - spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL]); - kfree(ctx); - } else { - pd->app_ctx[OZ_APPID_SERIAL] = ctx; - spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL]); - } - spin_lock(&g_cdev.lock); - if ((g_cdev.active_pd == NULL) && - ether_addr_equal(pd->mac_addr, g_cdev.active_addr)) { - oz_pd_get(pd); - g_cdev.active_pd = pd; - oz_dbg(ON, "Active PD arrived\n"); - } - spin_unlock(&g_cdev.lock); - oz_dbg(ON, "Serial service started\n"); - return 0; -} - -/* - * Context: softirq or process - */ -void oz_cdev_stop(struct oz_pd *pd, int pause) -{ - struct oz_serial_ctx *ctx; - - if (pause) { - oz_dbg(ON, "Serial service paused\n"); - return; - } - spin_lock_bh(&pd->app_lock[OZ_APPID_SERIAL]); - ctx = (struct oz_serial_ctx *) pd->app_ctx[OZ_APPID_SERIAL]; - pd->app_ctx[OZ_APPID_SERIAL] = NULL; - spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL]); - if (ctx) - oz_cdev_release_ctx(ctx); - spin_lock(&g_cdev.lock); - if (pd == g_cdev.active_pd) - g_cdev.active_pd = NULL; - else - pd = NULL; - spin_unlock(&g_cdev.lock); - if (pd) { - oz_pd_put(pd); - oz_dbg(ON, "Active PD departed\n"); - } - oz_dbg(ON, "Serial service stopped\n"); -} - -/* - * Context: softirq-serialized - */ -void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt) -{ - struct oz_serial_ctx *ctx; - struct oz_app_hdr *app_hdr; - u8 *data; - int len; - int space; - int copy_sz; - int ix; - - ctx = oz_cdev_claim_ctx(pd); - if (ctx == NULL) { - oz_dbg(ON, "Cannot claim serial context\n"); - return; - } - - app_hdr = (struct oz_app_hdr *)(elt+1); - /* If sequence number is non-zero then check it is not a duplicate. - */ - if (app_hdr->elt_seq_num != 0) { - if (((ctx->rx_seq_num - app_hdr->elt_seq_num) & 0x80) == 0) { - /* Reject duplicate element. */ - oz_dbg(ON, "Duplicate element:%02x %02x\n", - app_hdr->elt_seq_num, ctx->rx_seq_num); - goto out; - } - } - ctx->rx_seq_num = app_hdr->elt_seq_num; - len = elt->length - sizeof(struct oz_app_hdr); - data = ((u8 *)(elt+1)) + sizeof(struct oz_app_hdr); - if (len <= 0) - goto out; - space = ctx->rd_out - ctx->rd_in - 1; - if (space < 0) - space += OZ_RD_BUF_SZ; - if (len > space) { - oz_dbg(ON, "Not enough space:%d %d\n", len, space); - len = space; - } - ix = ctx->rd_in; - copy_sz = OZ_RD_BUF_SZ - ix; - if (copy_sz > len) - copy_sz = len; - memcpy(&ctx->rd_buf[ix], data, copy_sz); - len -= copy_sz; - ix += copy_sz; - if (ix == OZ_RD_BUF_SZ) - ix = 0; - if (len) { - memcpy(ctx->rd_buf, data+copy_sz, len); - ix = len; - } - ctx->rd_in = ix; - wake_up(&g_cdev.rdq); -out: - oz_cdev_release_ctx(ctx); -} diff --git a/drivers/staging/ozwpan/ozcdev.h b/drivers/staging/ozwpan/ozcdev.h deleted file mode 100644 index dd11935a093f..000000000000 --- a/drivers/staging/ozwpan/ozcdev.h +++ /dev/null @@ -1,17 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * ----------------------------------------------------------------------------- - */ -#ifndef _OZCDEV_H -#define _OZCDEV_H - -int oz_cdev_register(void); -int oz_cdev_deregister(void); -int oz_cdev_init(void); -void oz_cdev_term(void); -int oz_cdev_start(struct oz_pd *pd, int resume); -void oz_cdev_stop(struct oz_pd *pd, int pause); -void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt); - -#endif /* _OZCDEV_H */ diff --git a/drivers/staging/ozwpan/ozdbg.h b/drivers/staging/ozwpan/ozdbg.h deleted file mode 100644 index b86a2b7e0178..000000000000 --- a/drivers/staging/ozwpan/ozdbg.h +++ /dev/null @@ -1,54 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * ---------------------------------------------------------------------------*/ - -#ifndef _OZDBG_H -#define _OZDBG_H - -#define OZ_WANT_DBG 0 -#define OZ_WANT_VERBOSE_DBG 1 - -#define OZ_DBG_ON 0x0 -#define OZ_DBG_STREAM 0x1 -#define OZ_DBG_URB 0x2 -#define OZ_DBG_CTRL_DETAIL 0x4 -#define OZ_DBG_HUB 0x8 -#define OZ_DBG_RX_FRAMES 0x10 -#define OZ_DBG_TX_FRAMES 0x20 - -#define OZ_DEFAULT_DBG_MASK \ - ( \ - /* OZ_DBG_STREAM | */ \ - /* OZ_DBG_URB | */ \ - /* OZ_DBG_CTRL_DETAIL | */ \ - OZ_DBG_HUB | \ - /* OZ_DBG_RX_FRAMES | */ \ - /* OZ_DBG_TX_FRAMES | */ \ - 0) - -extern unsigned int oz_dbg_mask; - -#define oz_want_dbg(mask) \ - ((OZ_WANT_DBG && (OZ_DBG_##mask == OZ_DBG_ON)) || \ - (OZ_WANT_VERBOSE_DBG && (OZ_DBG_##mask & oz_dbg_mask))) - -#define oz_dbg(mask, fmt, ...) \ -do { \ - if (oz_want_dbg(mask)) \ - pr_debug(fmt, ##__VA_ARGS__); \ -} while (0) - -#define oz_cdev_dbg(cdev, mask, fmt, ...) \ -do { \ - if (oz_want_dbg(mask)) \ - netdev_dbg((cdev)->dev, fmt, ##__VA_ARGS__); \ -} while (0) - -#define oz_pd_dbg(pd, mask, fmt, ...) \ -do { \ - if (oz_want_dbg(mask)) \ - pr_debug(fmt, ##__VA_ARGS__); \ -} while (0) - -#endif /* _OZDBG_H */ diff --git a/drivers/staging/ozwpan/ozeltbuf.c b/drivers/staging/ozwpan/ozeltbuf.c deleted file mode 100644 index 01b25da44241..000000000000 --- a/drivers/staging/ozwpan/ozeltbuf.c +++ /dev/null @@ -1,252 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * ----------------------------------------------------------------------------- - */ -#include <linux/module.h> -#include <linux/netdevice.h> -#include "ozdbg.h" -#include "ozprotocol.h" -#include "ozeltbuf.h" -#include "ozpd.h" - -/* - * Context: softirq-serialized - */ -void oz_elt_buf_init(struct oz_elt_buf *buf) -{ - memset(buf, 0, sizeof(struct oz_elt_buf)); - INIT_LIST_HEAD(&buf->stream_list); - INIT_LIST_HEAD(&buf->order_list); - INIT_LIST_HEAD(&buf->isoc_list); - spin_lock_init(&buf->lock); -} - -/* - * Context: softirq or process - */ -void oz_elt_buf_term(struct oz_elt_buf *buf) -{ - struct oz_elt_info *ei, *n; - - list_for_each_entry_safe(ei, n, &buf->isoc_list, link_order) - kfree(ei); - list_for_each_entry_safe(ei, n, &buf->order_list, link_order) - kfree(ei); -} - -/* - * Context: softirq or process - */ -struct oz_elt_info *oz_elt_info_alloc(struct oz_elt_buf *buf) -{ - struct oz_elt_info *ei; - - ei = kmem_cache_zalloc(oz_elt_info_cache, GFP_ATOMIC); - if (ei) { - INIT_LIST_HEAD(&ei->link); - INIT_LIST_HEAD(&ei->link_order); - } - return ei; -} - -/* - * Precondition: oz_elt_buf.lock must be held. - * Context: softirq or process - */ -void oz_elt_info_free(struct oz_elt_buf *buf, struct oz_elt_info *ei) -{ - if (ei) - kmem_cache_free(oz_elt_info_cache, ei); -} - -/*------------------------------------------------------------------------------ - * Context: softirq - */ -void oz_elt_info_free_chain(struct oz_elt_buf *buf, struct list_head *list) -{ - struct oz_elt_info *ei, *n; - - spin_lock_bh(&buf->lock); - list_for_each_entry_safe(ei, n, list->next, link) - oz_elt_info_free(buf, ei); - spin_unlock_bh(&buf->lock); -} - -int oz_elt_stream_create(struct oz_elt_buf *buf, u8 id, int max_buf_count) -{ - struct oz_elt_stream *st; - - oz_dbg(ON, "%s: (0x%x)\n", __func__, id); - - st = kzalloc(sizeof(struct oz_elt_stream), GFP_ATOMIC); - if (st == NULL) - return -ENOMEM; - atomic_set(&st->ref_count, 1); - st->id = id; - st->max_buf_count = max_buf_count; - INIT_LIST_HEAD(&st->elt_list); - spin_lock_bh(&buf->lock); - list_add_tail(&st->link, &buf->stream_list); - spin_unlock_bh(&buf->lock); - return 0; -} - -int oz_elt_stream_delete(struct oz_elt_buf *buf, u8 id) -{ - struct list_head *e, *n; - struct oz_elt_stream *st = NULL; - - oz_dbg(ON, "%s: (0x%x)\n", __func__, id); - spin_lock_bh(&buf->lock); - list_for_each(e, &buf->stream_list) { - st = list_entry(e, struct oz_elt_stream, link); - if (st->id == id) { - list_del(e); - break; - } - st = NULL; - } - if (!st) { - spin_unlock_bh(&buf->lock); - return -1; - } - list_for_each_safe(e, n, &st->elt_list) { - struct oz_elt_info *ei = - list_entry(e, struct oz_elt_info, link); - list_del_init(&ei->link); - list_del_init(&ei->link_order); - st->buf_count -= ei->length; - oz_dbg(STREAM, "Stream down: %d %d %d\n", - st->buf_count, ei->length, atomic_read(&st->ref_count)); - oz_elt_stream_put(st); - oz_elt_info_free(buf, ei); - } - spin_unlock_bh(&buf->lock); - oz_elt_stream_put(st); - return 0; -} - -void oz_elt_stream_get(struct oz_elt_stream *st) -{ - atomic_inc(&st->ref_count); -} - -void oz_elt_stream_put(struct oz_elt_stream *st) -{ - if (atomic_dec_and_test(&st->ref_count)) { - oz_dbg(ON, "Stream destroyed\n"); - kfree(st); - } -} - -/* - * Precondition: Element buffer lock must be held. - * If this function fails the caller is responsible for deallocating the elt - * info structure. - */ -int oz_queue_elt_info(struct oz_elt_buf *buf, u8 isoc, u8 id, - struct oz_elt_info *ei) -{ - struct oz_elt_stream *st = NULL; - struct list_head *e; - - if (id) { - list_for_each(e, &buf->stream_list) { - st = list_entry(e, struct oz_elt_stream, link); - if (st->id == id) - break; - } - if (e == &buf->stream_list) { - /* Stream specified but stream not known so fail. - * Caller deallocates element info. */ - return -1; - } - } - if (st) { - /* If this is an ISOC fixed element that needs a frame number - * then insert that now. Earlier we stored the unit count in - * this field. - */ - struct oz_isoc_fixed *body = (struct oz_isoc_fixed *) - &ei->data[sizeof(struct oz_elt)]; - if ((body->app_id == OZ_APPID_USB) && (body->type - == OZ_USB_ENDPOINT_DATA) && - (body->format == OZ_DATA_F_ISOC_FIXED)) { - u8 unit_count = body->frame_number; - - body->frame_number = st->frame_number; - st->frame_number += unit_count; - } - /* Claim stream and update accounts */ - oz_elt_stream_get(st); - ei->stream = st; - st->buf_count += ei->length; - /* Add to list in stream. */ - list_add_tail(&ei->link, &st->elt_list); - oz_dbg(STREAM, "Stream up: %d %d\n", st->buf_count, ei->length); - /* Check if we have too much buffered for this stream. If so - * start dropping elements until we are back in bounds. - */ - while ((st->buf_count > st->max_buf_count) && - !list_empty(&st->elt_list)) { - struct oz_elt_info *ei2 = - list_first_entry(&st->elt_list, - struct oz_elt_info, link); - list_del_init(&ei2->link); - list_del_init(&ei2->link_order); - st->buf_count -= ei2->length; - oz_elt_info_free(buf, ei2); - oz_elt_stream_put(st); - } - } - list_add_tail(&ei->link_order, isoc ? - &buf->isoc_list : &buf->order_list); - return 0; -} - -int oz_select_elts_for_tx(struct oz_elt_buf *buf, u8 isoc, unsigned *len, - unsigned max_len, struct list_head *list) -{ - int count = 0; - struct list_head *el; - struct oz_elt_info *ei, *n; - - spin_lock_bh(&buf->lock); - if (isoc) - el = &buf->isoc_list; - else - el = &buf->order_list; - - list_for_each_entry_safe(ei, n, el, link_order) { - if ((*len + ei->length) <= max_len) { - struct oz_app_hdr *app_hdr = (struct oz_app_hdr *) - &ei->data[sizeof(struct oz_elt)]; - app_hdr->elt_seq_num = buf->tx_seq_num[ei->app_id]++; - if (buf->tx_seq_num[ei->app_id] == 0) - buf->tx_seq_num[ei->app_id] = 1; - *len += ei->length; - list_del(&ei->link); - list_del(&ei->link_order); - if (ei->stream) { - ei->stream->buf_count -= ei->length; - oz_dbg(STREAM, "Stream down: %d %d\n", - ei->stream->buf_count, ei->length); - oz_elt_stream_put(ei->stream); - ei->stream = NULL; - } - INIT_LIST_HEAD(&ei->link_order); - list_add_tail(&ei->link, list); - count++; - } else { - break; - } - } - spin_unlock_bh(&buf->lock); - return count; -} - -int oz_are_elts_available(struct oz_elt_buf *buf) -{ - return !list_empty(&buf->order_list); -} diff --git a/drivers/staging/ozwpan/ozeltbuf.h b/drivers/staging/ozwpan/ozeltbuf.h deleted file mode 100644 index f09f5fe3ffbe..000000000000 --- a/drivers/staging/ozwpan/ozeltbuf.h +++ /dev/null @@ -1,65 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * ----------------------------------------------------------------------------- - */ -#ifndef _OZELTBUF_H -#define _OZELTBUF_H - -#include "ozprotocol.h" - -/*----------------------------------------------------------------------------- - */ -struct oz_pd; -typedef void (*oz_elt_callback_t)(struct oz_pd *pd, long context); - -struct oz_elt_stream { - struct list_head link; - struct list_head elt_list; - atomic_t ref_count; - unsigned buf_count; - unsigned max_buf_count; - u8 frame_number; - u8 id; -}; - -#define OZ_MAX_ELT_PAYLOAD 255 -struct oz_elt_info { - struct list_head link; - struct list_head link_order; - u8 flags; - u8 app_id; - oz_elt_callback_t callback; - long context; - struct oz_elt_stream *stream; - u8 data[sizeof(struct oz_elt) + OZ_MAX_ELT_PAYLOAD]; - int length; -}; -/* Flags values */ -#define OZ_EI_F_MARKED 0x1 - -struct oz_elt_buf { - spinlock_t lock; - struct list_head stream_list; - struct list_head order_list; - struct list_head isoc_list; - u8 tx_seq_num[OZ_NB_APPS]; -}; - -void oz_elt_buf_init(struct oz_elt_buf *buf); -void oz_elt_buf_term(struct oz_elt_buf *buf); -struct oz_elt_info *oz_elt_info_alloc(struct oz_elt_buf *buf); -void oz_elt_info_free(struct oz_elt_buf *buf, struct oz_elt_info *ei); -void oz_elt_info_free_chain(struct oz_elt_buf *buf, struct list_head *list); -int oz_elt_stream_create(struct oz_elt_buf *buf, u8 id, int max_buf_count); -int oz_elt_stream_delete(struct oz_elt_buf *buf, u8 id); -void oz_elt_stream_get(struct oz_elt_stream *st); -void oz_elt_stream_put(struct oz_elt_stream *st); -int oz_queue_elt_info(struct oz_elt_buf *buf, u8 isoc, u8 id, - struct oz_elt_info *ei); -int oz_select_elts_for_tx(struct oz_elt_buf *buf, u8 isoc, unsigned *len, - unsigned max_len, struct list_head *list); -int oz_are_elts_available(struct oz_elt_buf *buf); - -#endif /* _OZELTBUF_H */ - diff --git a/drivers/staging/ozwpan/ozhcd.c b/drivers/staging/ozwpan/ozhcd.c deleted file mode 100644 index 784b5ecfa849..000000000000 --- a/drivers/staging/ozwpan/ozhcd.c +++ /dev/null @@ -1,2301 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * - * This file provides the implementation of a USB host controller device that - * does not have any associated hardware. Instead the virtual device is - * connected to the WiFi network and emulates the operation of a USB hcd by - * receiving and sending network frames. - * Note: - * We take great pains to reduce the amount of code where interrupts need to be - * disabled and in this respect we are different from standard HCD's. In - * particular we don't want in_irq() code bleeding over to the protocol side of - * the driver. - * The troublesome functions are the urb enqueue and dequeue functions both of - * which can be called in_irq(). So for these functions we put the urbs into a - * queue and request a tasklet to process them. This means that a spinlock with - * interrupts disabled must be held for insertion and removal but most code is - * is in tasklet or soft irq context. The lock that protects this list is called - * the tasklet lock and serves the purpose of the 'HCD lock' which must be held - * when calling the following functions. - * usb_hcd_link_urb_to_ep() - * usb_hcd_unlink_urb_from_ep() - * usb_hcd_flush_endpoint() - * usb_hcd_check_unlink_urb() - * ----------------------------------------------------------------------------- - */ -#include <linux/platform_device.h> -#include <linux/usb.h> -#include <linux/slab.h> -#include <linux/export.h> -#include "linux/usb/hcd.h" -#include <asm/unaligned.h> -#include "ozdbg.h" -#include "ozusbif.h" -#include "ozurbparanoia.h" -#include "ozhcd.h" - -/* - * Number of units of buffering to capture for an isochronous IN endpoint before - * allowing data to be indicated up. - */ -#define OZ_IN_BUFFERING_UNITS 100 - -/* Name of our platform device. - */ -#define OZ_PLAT_DEV_NAME "ozwpan" - -/*EP0 timeout before ep0 request is again added to TX queue. (13*8 = 98mSec) - */ -#define EP0_TIMEOUT_COUNTER 13 - -/* Debounce time HCD driver should wait before unregistering. - */ -#define OZ_HUB_DEBOUNCE_TIMEOUT 1500 - -/* - * Used to link urbs together and also store some status information for each - * urb. - * A cache of these are kept in a pool to reduce number of calls to kmalloc. - */ -struct oz_urb_link { - struct list_head link; - struct urb *urb; - struct oz_port *port; - u8 req_id; - u8 ep_num; - unsigned submit_counter; -}; - -static struct kmem_cache *oz_urb_link_cache; - -/* Holds state information about a USB endpoint. - */ -#define OZ_EP_BUFFER_SIZE_ISOC (1024 * 24) -#define OZ_EP_BUFFER_SIZE_INT 512 -struct oz_endpoint { - struct list_head urb_list; /* List of oz_urb_link items. */ - struct list_head link; /* For isoc ep, links in to isoc - lists of oz_port. */ - struct timespec timestamp; - int credit; - int credit_ceiling; - u8 ep_num; - u8 attrib; - u8 *buffer; - int buffer_size; - int in_ix; - int out_ix; - int buffered_units; - unsigned flags; - int start_frame; -}; - -/* Bits in the flags field. */ -#define OZ_F_EP_BUFFERING 0x1 -#define OZ_F_EP_HAVE_STREAM 0x2 - -/* Holds state information about a USB interface. - */ -struct oz_interface { - unsigned ep_mask; - u8 alt; -}; - -/* Holds state information about an hcd port. - */ -#define OZ_NB_ENDPOINTS 16 -struct oz_port { - unsigned flags; - unsigned status; - void *hpd; - struct oz_hcd *ozhcd; - spinlock_t port_lock; - u8 bus_addr; - u8 next_req_id; - u8 config_num; - int num_iface; - struct oz_interface *iface; - struct oz_endpoint *out_ep[OZ_NB_ENDPOINTS]; - struct oz_endpoint *in_ep[OZ_NB_ENDPOINTS]; - struct list_head isoc_out_ep; - struct list_head isoc_in_ep; -}; - -#define OZ_PORT_F_PRESENT 0x1 -#define OZ_PORT_F_CHANGED 0x2 -#define OZ_PORT_F_DYING 0x4 - -/* Data structure in the private context area of struct usb_hcd. - */ -#define OZ_NB_PORTS 8 -struct oz_hcd { - spinlock_t hcd_lock; - struct list_head urb_pending_list; - struct list_head urb_cancel_list; - struct list_head orphanage; - int conn_port; /* Port that is currently connecting, -1 if none.*/ - struct oz_port ports[OZ_NB_PORTS]; - uint flags; - struct usb_hcd *hcd; -}; - -/* Bits in flags field. - */ -#define OZ_HDC_F_SUSPENDED 0x1 - -/* - * Static function prototypes. - */ -static int oz_hcd_start(struct usb_hcd *hcd); -static void oz_hcd_stop(struct usb_hcd *hcd); -static void oz_hcd_shutdown(struct usb_hcd *hcd); -static int oz_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, - gfp_t mem_flags); -static int oz_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status); -static void oz_hcd_endpoint_disable(struct usb_hcd *hcd, - struct usb_host_endpoint *ep); -static void oz_hcd_endpoint_reset(struct usb_hcd *hcd, - struct usb_host_endpoint *ep); -static int oz_hcd_get_frame_number(struct usb_hcd *hcd); -static int oz_hcd_hub_status_data(struct usb_hcd *hcd, char *buf); -static int oz_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 wvalue, - u16 windex, char *buf, u16 wlength); -static int oz_hcd_bus_suspend(struct usb_hcd *hcd); -static int oz_hcd_bus_resume(struct usb_hcd *hcd); -static int oz_plat_probe(struct platform_device *dev); -static int oz_plat_remove(struct platform_device *dev); -static void oz_plat_shutdown(struct platform_device *dev); -static int oz_plat_suspend(struct platform_device *dev, pm_message_t msg); -static int oz_plat_resume(struct platform_device *dev); -static void oz_urb_process_tasklet(unsigned long unused); -static int oz_build_endpoints_for_config(struct usb_hcd *hcd, - struct oz_port *port, struct usb_host_config *config, - gfp_t mem_flags); -static void oz_clean_endpoints_for_config(struct usb_hcd *hcd, - struct oz_port *port); -static int oz_build_endpoints_for_interface(struct usb_hcd *hcd, - struct oz_port *port, - struct usb_host_interface *intf, gfp_t mem_flags); -static void oz_clean_endpoints_for_interface(struct usb_hcd *hcd, - struct oz_port *port, int if_ix); -static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb, - gfp_t mem_flags); -static struct oz_urb_link *oz_remove_urb(struct oz_endpoint *ep, - struct urb *urb); -static void oz_hcd_clear_orphanage(struct oz_hcd *ozhcd, int status); - -/* - * Static external variables. - */ -static struct platform_device *g_plat_dev; -static struct oz_hcd *g_ozhcd; -static DEFINE_SPINLOCK(g_hcdlock); /* Guards g_ozhcd. */ -static const char g_hcd_name[] = "Ozmo WPAN"; -static DEFINE_SPINLOCK(g_tasklet_lock); -static struct tasklet_struct g_urb_process_tasklet; -static struct tasklet_struct g_urb_cancel_tasklet; -static atomic_t g_pending_urbs = ATOMIC_INIT(0); -static atomic_t g_usb_frame_number = ATOMIC_INIT(0); -static const struct hc_driver g_oz_hc_drv = { - .description = g_hcd_name, - .product_desc = "Ozmo Devices WPAN", - .hcd_priv_size = sizeof(struct oz_hcd), - .flags = HCD_USB11, - .start = oz_hcd_start, - .stop = oz_hcd_stop, - .shutdown = oz_hcd_shutdown, - .urb_enqueue = oz_hcd_urb_enqueue, - .urb_dequeue = oz_hcd_urb_dequeue, - .endpoint_disable = oz_hcd_endpoint_disable, - .endpoint_reset = oz_hcd_endpoint_reset, - .get_frame_number = oz_hcd_get_frame_number, - .hub_status_data = oz_hcd_hub_status_data, - .hub_control = oz_hcd_hub_control, - .bus_suspend = oz_hcd_bus_suspend, - .bus_resume = oz_hcd_bus_resume, -}; - -static struct platform_driver g_oz_plat_drv = { - .probe = oz_plat_probe, - .remove = oz_plat_remove, - .shutdown = oz_plat_shutdown, - .suspend = oz_plat_suspend, - .resume = oz_plat_resume, - .driver = { - .name = OZ_PLAT_DEV_NAME, - }, -}; - -/* - * Gets our private context area (which is of type struct oz_hcd) from the - * usb_hcd structure. - * Context: any - */ -static inline struct oz_hcd *oz_hcd_private(struct usb_hcd *hcd) -{ - return (struct oz_hcd *)hcd->hcd_priv; -} - -/* - * Searches list of ports to find the index of the one with a specified USB - * bus address. If none of the ports has the bus address then the connection - * port is returned, if there is one or -1 otherwise. - * Context: any - */ -static int oz_get_port_from_addr(struct oz_hcd *ozhcd, u8 bus_addr) -{ - int i; - - for (i = 0; i < OZ_NB_PORTS; i++) { - if (ozhcd->ports[i].bus_addr == bus_addr) - return i; - } - return ozhcd->conn_port; -} - -/* - * Context: any - */ -static struct oz_urb_link *oz_alloc_urb_link(void) -{ - return kmem_cache_alloc(oz_urb_link_cache, GFP_ATOMIC); -} - -/* - * Context: any - */ -static void oz_free_urb_link(struct oz_urb_link *urbl) -{ - if (!urbl) - return; - - kmem_cache_free(oz_urb_link_cache, urbl); -} - -/* - * Allocates endpoint structure and optionally a buffer. If a buffer is - * allocated it immediately follows the endpoint structure. - * Context: softirq - */ -static struct oz_endpoint *oz_ep_alloc(int buffer_size, gfp_t mem_flags) -{ - struct oz_endpoint *ep; - - ep = kzalloc(sizeof(struct oz_endpoint)+buffer_size, mem_flags); - if (!ep) - return NULL; - - INIT_LIST_HEAD(&ep->urb_list); - INIT_LIST_HEAD(&ep->link); - ep->credit = -1; - if (buffer_size) { - ep->buffer_size = buffer_size; - ep->buffer = (u8 *)(ep+1); - } - - return ep; -} - -/* - * Pre-condition: Must be called with g_tasklet_lock held and interrupts - * disabled. - * Context: softirq or process - */ -static struct oz_urb_link *oz_uncancel_urb(struct oz_hcd *ozhcd, - struct urb *urb) -{ - struct oz_urb_link *urbl; - - list_for_each_entry(urbl, &ozhcd->urb_cancel_list, link) { - if (urb == urbl->urb) { - list_del_init(&urbl->link); - return urbl; - } - } - return NULL; -} - -/* - * This is called when we have finished processing an urb. It unlinks it from - * the ep and returns it to the core. - * Context: softirq or process - */ -static void oz_complete_urb(struct usb_hcd *hcd, struct urb *urb, - int status) -{ - struct oz_hcd *ozhcd = oz_hcd_private(hcd); - unsigned long irq_state; - struct oz_urb_link *cancel_urbl; - - spin_lock_irqsave(&g_tasklet_lock, irq_state); - usb_hcd_unlink_urb_from_ep(hcd, urb); - /* Clear hcpriv which will prevent it being put in the cancel list - * in the event that an attempt is made to cancel it. - */ - urb->hcpriv = NULL; - /* Walk the cancel list in case the urb is already sitting there. - * Since we process the cancel list in a tasklet rather than in - * the dequeue function this could happen. - */ - cancel_urbl = oz_uncancel_urb(ozhcd, urb); - /* Note: we release lock but do not enable local irqs. - * It appears that usb_hcd_giveback_urb() expects irqs to be disabled, - * or at least other host controllers disable interrupts at this point - * so we do the same. We must, however, release the lock otherwise a - * deadlock will occur if an urb is submitted to our driver in the urb - * completion function. Because we disable interrupts it is possible - * that the urb_enqueue function can be called with them disabled. - */ - spin_unlock(&g_tasklet_lock); - if (oz_forget_urb(urb)) { - oz_dbg(ON, "ERROR Unknown URB %p\n", urb); - } else { - atomic_dec(&g_pending_urbs); - usb_hcd_giveback_urb(hcd, urb, status); - } - spin_lock(&g_tasklet_lock); - spin_unlock_irqrestore(&g_tasklet_lock, irq_state); - oz_free_urb_link(cancel_urbl); -} - -/* - * Deallocates an endpoint including deallocating any associated stream and - * returning any queued urbs to the core. - * Context: softirq - */ -static void oz_ep_free(struct oz_port *port, struct oz_endpoint *ep) -{ - if (port) { - LIST_HEAD(list); - struct oz_hcd *ozhcd = port->ozhcd; - - if (ep->flags & OZ_F_EP_HAVE_STREAM) - oz_usb_stream_delete(port->hpd, ep->ep_num); - /* Transfer URBs to the orphanage while we hold the lock. */ - spin_lock_bh(&ozhcd->hcd_lock); - /* Note: this works even if ep->urb_list is empty.*/ - list_replace_init(&ep->urb_list, &list); - /* Put the URBs in the orphanage. */ - list_splice_tail(&list, &ozhcd->orphanage); - spin_unlock_bh(&ozhcd->hcd_lock); - } - oz_dbg(ON, "Freeing endpoint memory\n"); - kfree(ep); -} - -/* - * Context: softirq - */ -static void oz_complete_buffered_urb(struct oz_port *port, - struct oz_endpoint *ep, - struct urb *urb) -{ - int data_len, available_space, copy_len; - - data_len = ep->buffer[ep->out_ix]; - if (data_len <= urb->transfer_buffer_length) - available_space = data_len; - else - available_space = urb->transfer_buffer_length; - - if (++ep->out_ix == ep->buffer_size) - ep->out_ix = 0; - copy_len = ep->buffer_size - ep->out_ix; - if (copy_len >= available_space) - copy_len = available_space; - memcpy(urb->transfer_buffer, &ep->buffer[ep->out_ix], copy_len); - - if (copy_len < available_space) { - memcpy((urb->transfer_buffer + copy_len), ep->buffer, - (available_space - copy_len)); - ep->out_ix = available_space - copy_len; - } else { - ep->out_ix += copy_len; - } - urb->actual_length = available_space; - if (ep->out_ix == ep->buffer_size) - ep->out_ix = 0; - - ep->buffered_units--; - oz_dbg(ON, "Trying to give back buffered frame of size=%d\n", - available_space); - oz_complete_urb(port->ozhcd->hcd, urb, 0); -} - -/* - * Context: softirq - */ -static int oz_enqueue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir, - struct urb *urb, u8 req_id) -{ - struct oz_urb_link *urbl; - struct oz_endpoint *ep = NULL; - int err = 0; - - if (ep_addr >= OZ_NB_ENDPOINTS) { - oz_dbg(ON, "%s: Invalid endpoint number\n", __func__); - return -EINVAL; - } - urbl = oz_alloc_urb_link(); - if (!urbl) - return -ENOMEM; - urbl->submit_counter = 0; - urbl->urb = urb; - urbl->req_id = req_id; - urbl->ep_num = ep_addr; - /* Hold lock while we insert the URB into the list within the - * endpoint structure. - */ - spin_lock_bh(&port->ozhcd->hcd_lock); - /* If the urb has been unlinked while out of any list then - * complete it now. - */ - if (urb->unlinked) { - spin_unlock_bh(&port->ozhcd->hcd_lock); - oz_dbg(ON, "urb %p unlinked so complete immediately\n", urb); - oz_complete_urb(port->ozhcd->hcd, urb, 0); - oz_free_urb_link(urbl); - return 0; - } - - if (in_dir) - ep = port->in_ep[ep_addr]; - else - ep = port->out_ep[ep_addr]; - if (!ep) { - err = -ENOMEM; - goto out; - } - - /*For interrupt endpoint check for buffered data - * & complete urb - */ - if (((ep->attrib & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) - && ep->buffered_units > 0) { - oz_free_urb_link(urbl); - spin_unlock_bh(&port->ozhcd->hcd_lock); - oz_complete_buffered_urb(port, ep, urb); - return 0; - } - - if (port->hpd) { - list_add_tail(&urbl->link, &ep->urb_list); - if (!in_dir && ep_addr && (ep->credit < 0)) { - getrawmonotonic(&ep->timestamp); - ep->credit = 0; - } - } else { - err = -EPIPE; - } -out: - spin_unlock_bh(&port->ozhcd->hcd_lock); - if (err) - oz_free_urb_link(urbl); - return err; -} - -/* - * Removes an urb from the queue in the endpoint. - * Returns 0 if it is found and -EIDRM otherwise. - * Context: softirq - */ -static int oz_dequeue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir, - struct urb *urb) -{ - struct oz_urb_link *urbl = NULL; - struct oz_endpoint *ep; - - spin_lock_bh(&port->ozhcd->hcd_lock); - if (in_dir) - ep = port->in_ep[ep_addr]; - else - ep = port->out_ep[ep_addr]; - if (ep) { - struct list_head *e; - - list_for_each(e, &ep->urb_list) { - urbl = list_entry(e, struct oz_urb_link, link); - if (urbl->urb == urb) { - list_del_init(e); - break; - } - urbl = NULL; - } - } - spin_unlock_bh(&port->ozhcd->hcd_lock); - oz_free_urb_link(urbl); - return urbl ? 0 : -EIDRM; -} - -/* - * Finds an urb given its request id. - * Context: softirq - */ -static struct urb *oz_find_urb_by_id(struct oz_port *port, int ep_ix, - u8 req_id) -{ - struct oz_hcd *ozhcd = port->ozhcd; - struct urb *urb = NULL; - struct oz_urb_link *urbl; - struct oz_endpoint *ep; - - spin_lock_bh(&ozhcd->hcd_lock); - ep = port->out_ep[ep_ix]; - if (ep) { - struct list_head *e; - - list_for_each(e, &ep->urb_list) { - urbl = list_entry(e, struct oz_urb_link, link); - if (urbl->req_id == req_id) { - urb = urbl->urb; - list_del_init(e); - break; - } - } - } - spin_unlock_bh(&ozhcd->hcd_lock); - /* If urb is non-zero then we we must have an urb link to delete. - */ - if (urb) - oz_free_urb_link(urbl); - return urb; -} - -/* - * Pre-condition: Port lock must be held. - * Context: softirq - */ -static void oz_acquire_port(struct oz_port *port, void *hpd) -{ - INIT_LIST_HEAD(&port->isoc_out_ep); - INIT_LIST_HEAD(&port->isoc_in_ep); - port->flags |= OZ_PORT_F_PRESENT | OZ_PORT_F_CHANGED; - port->status |= USB_PORT_STAT_CONNECTION | - (USB_PORT_STAT_C_CONNECTION << 16); - oz_usb_get(hpd); - port->hpd = hpd; -} - -/* - * Context: softirq - */ -static struct oz_hcd *oz_hcd_claim(void) -{ - struct oz_hcd *ozhcd; - - spin_lock_bh(&g_hcdlock); - ozhcd = g_ozhcd; - if (ozhcd) - usb_get_hcd(ozhcd->hcd); - spin_unlock_bh(&g_hcdlock); - return ozhcd; -} - -/* - * Context: softirq - */ -static inline void oz_hcd_put(struct oz_hcd *ozhcd) -{ - if (ozhcd) - usb_put_hcd(ozhcd->hcd); -} - -/* - * This is called by the protocol handler to notify that a PD has arrived. - * We allocate a port to associate with the PD and create a structure for - * endpoint 0. This port is made the connection port. - * In the event that one of the other port is already a connection port then - * we fail. - * TODO We should be able to do better than fail and should be able remember - * that this port needs configuring and make it the connection port once the - * current connection port has been assigned an address. Collisions here are - * probably very rare indeed. - * Context: softirq - */ -struct oz_port *oz_hcd_pd_arrived(void *hpd) -{ - int i; - struct oz_port *hport; - struct oz_hcd *ozhcd; - struct oz_endpoint *ep; - - ozhcd = oz_hcd_claim(); - if (!ozhcd) - return NULL; - /* Allocate an endpoint object in advance (before holding hcd lock) to - * use for out endpoint 0. - */ - ep = oz_ep_alloc(0, GFP_ATOMIC); - if (!ep) - goto err_put; - - spin_lock_bh(&ozhcd->hcd_lock); - if (ozhcd->conn_port >= 0) - goto err_unlock; - - for (i = 0; i < OZ_NB_PORTS; i++) { - struct oz_port *port = &ozhcd->ports[i]; - - spin_lock(&port->port_lock); - if (!(port->flags & (OZ_PORT_F_PRESENT | OZ_PORT_F_CHANGED))) { - oz_acquire_port(port, hpd); - spin_unlock(&port->port_lock); - break; - } - spin_unlock(&port->port_lock); - } - if (i == OZ_NB_PORTS) - goto err_unlock; - - ozhcd->conn_port = i; - hport = &ozhcd->ports[i]; - hport->out_ep[0] = ep; - spin_unlock_bh(&ozhcd->hcd_lock); - if (ozhcd->flags & OZ_HDC_F_SUSPENDED) - usb_hcd_resume_root_hub(ozhcd->hcd); - usb_hcd_poll_rh_status(ozhcd->hcd); - oz_hcd_put(ozhcd); - - return hport; - -err_unlock: - spin_unlock_bh(&ozhcd->hcd_lock); - oz_ep_free(NULL, ep); -err_put: - oz_hcd_put(ozhcd); - return NULL; -} - -/* - * This is called by the protocol handler to notify that the PD has gone away. - * We need to deallocate all resources and then request that the root hub is - * polled. We release the reference we hold on the PD. - * Context: softirq - */ -void oz_hcd_pd_departed(struct oz_port *port) -{ - struct oz_hcd *ozhcd; - void *hpd; - struct oz_endpoint *ep = NULL; - - if (port == NULL) { - oz_dbg(ON, "%s: port = 0\n", __func__); - return; - } - ozhcd = port->ozhcd; - if (ozhcd == NULL) - return; - /* Check if this is the connection port - if so clear it. - */ - spin_lock_bh(&ozhcd->hcd_lock); - if ((ozhcd->conn_port >= 0) && - (port == &ozhcd->ports[ozhcd->conn_port])) { - oz_dbg(ON, "Clearing conn_port\n"); - ozhcd->conn_port = -1; - } - spin_lock(&port->port_lock); - port->flags |= OZ_PORT_F_DYING; - spin_unlock(&port->port_lock); - spin_unlock_bh(&ozhcd->hcd_lock); - - oz_clean_endpoints_for_config(ozhcd->hcd, port); - spin_lock_bh(&port->port_lock); - hpd = port->hpd; - port->hpd = NULL; - port->bus_addr = 0xff; - port->config_num = 0; - port->flags &= ~(OZ_PORT_F_PRESENT | OZ_PORT_F_DYING); - port->flags |= OZ_PORT_F_CHANGED; - port->status &= ~(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE); - port->status |= (USB_PORT_STAT_C_CONNECTION << 16); - /* If there is an endpont 0 then clear the pointer while we hold - * the spinlock be we deallocate it after releasing the lock. - */ - if (port->out_ep[0]) { - ep = port->out_ep[0]; - port->out_ep[0] = NULL; - } - spin_unlock_bh(&port->port_lock); - if (ep) - oz_ep_free(port, ep); - usb_hcd_poll_rh_status(ozhcd->hcd); - oz_usb_put(hpd); -} - -/* - * Context: softirq - */ -void oz_hcd_pd_reset(void *hpd, void *hport) -{ - /* Cleanup the current configuration and report reset to the core. - */ - struct oz_port *port = hport; - struct oz_hcd *ozhcd = port->ozhcd; - - oz_dbg(ON, "PD Reset\n"); - spin_lock_bh(&port->port_lock); - port->flags |= OZ_PORT_F_CHANGED; - port->status |= USB_PORT_STAT_RESET; - port->status |= (USB_PORT_STAT_C_RESET << 16); - spin_unlock_bh(&port->port_lock); - oz_clean_endpoints_for_config(ozhcd->hcd, port); - usb_hcd_poll_rh_status(ozhcd->hcd); -} - -/* - * Context: softirq - */ -void oz_hcd_get_desc_cnf(void *hport, u8 req_id, u8 status, const u8 *desc, - u8 length, u16 offset, u16 total_size) -{ - struct oz_port *port = hport; - struct urb *urb; - int err = 0; - - oz_dbg(ON, "oz_hcd_get_desc_cnf length = %d offs = %d tot_size = %d\n", - length, offset, total_size); - urb = oz_find_urb_by_id(port, 0, req_id); - if (!urb) - return; - if (status == 0) { - unsigned int copy_len; - unsigned int required_size = urb->transfer_buffer_length; - - if (required_size > total_size) - required_size = total_size; - copy_len = required_size-offset; - if (length <= copy_len) - copy_len = length; - memcpy(urb->transfer_buffer+offset, desc, copy_len); - offset += copy_len; - if (offset < required_size) { - struct usb_ctrlrequest *setup = - (struct usb_ctrlrequest *)urb->setup_packet; - unsigned wvalue = le16_to_cpu(setup->wValue); - - if (oz_enqueue_ep_urb(port, 0, 0, urb, req_id)) - err = -ENOMEM; - else if (oz_usb_get_desc_req(port->hpd, req_id, - setup->bRequestType, (u8)(wvalue>>8), - (u8)wvalue, setup->wIndex, offset, - required_size-offset)) { - oz_dequeue_ep_urb(port, 0, 0, urb); - err = -ENOMEM; - } - if (err == 0) - return; - } - } - urb->actual_length = total_size; - oz_complete_urb(port->ozhcd->hcd, urb, 0); -} - -/* - * Context: softirq - */ -static void oz_display_conf_type(u8 t) -{ - switch (t) { - case USB_REQ_GET_STATUS: - oz_dbg(ON, "USB_REQ_GET_STATUS - cnf\n"); - break; - case USB_REQ_CLEAR_FEATURE: - oz_dbg(ON, "USB_REQ_CLEAR_FEATURE - cnf\n"); - break; - case USB_REQ_SET_FEATURE: - oz_dbg(ON, "USB_REQ_SET_FEATURE - cnf\n"); - break; - case USB_REQ_SET_ADDRESS: - oz_dbg(ON, "USB_REQ_SET_ADDRESS - cnf\n"); - break; - case USB_REQ_GET_DESCRIPTOR: - oz_dbg(ON, "USB_REQ_GET_DESCRIPTOR - cnf\n"); - break; - case USB_REQ_SET_DESCRIPTOR: - oz_dbg(ON, "USB_REQ_SET_DESCRIPTOR - cnf\n"); - break; - case USB_REQ_GET_CONFIGURATION: - oz_dbg(ON, "USB_REQ_GET_CONFIGURATION - cnf\n"); - break; - case USB_REQ_SET_CONFIGURATION: - oz_dbg(ON, "USB_REQ_SET_CONFIGURATION - cnf\n"); - break; - case USB_REQ_GET_INTERFACE: - oz_dbg(ON, "USB_REQ_GET_INTERFACE - cnf\n"); - break; - case USB_REQ_SET_INTERFACE: - oz_dbg(ON, "USB_REQ_SET_INTERFACE - cnf\n"); - break; - case USB_REQ_SYNCH_FRAME: - oz_dbg(ON, "USB_REQ_SYNCH_FRAME - cnf\n"); - break; - } -} - -/* - * Context: softirq - */ -static void oz_hcd_complete_set_config(struct oz_port *port, struct urb *urb, - u8 rcode, u8 config_num) -{ - int rc = 0; - struct usb_hcd *hcd = port->ozhcd->hcd; - - if (rcode == 0) { - port->config_num = config_num; - oz_clean_endpoints_for_config(hcd, port); - if (oz_build_endpoints_for_config(hcd, port, - &urb->dev->config[port->config_num-1], GFP_ATOMIC)) { - rc = -ENOMEM; - } - } else { - rc = -ENOMEM; - } - oz_complete_urb(hcd, urb, rc); -} - -/* - * Context: softirq - */ -static void oz_hcd_complete_set_interface(struct oz_port *port, struct urb *urb, - u8 rcode, u8 if_num, u8 alt) -{ - struct usb_hcd *hcd = port->ozhcd->hcd; - int rc = 0; - - if ((rcode == 0) && (port->config_num > 0)) { - struct usb_host_config *config; - struct usb_host_interface *intf; - - oz_dbg(ON, "Set interface %d alt %d\n", if_num, alt); - oz_clean_endpoints_for_interface(hcd, port, if_num); - config = &urb->dev->config[port->config_num-1]; - intf = &config->intf_cache[if_num]->altsetting[alt]; - if (oz_build_endpoints_for_interface(hcd, port, intf, - GFP_ATOMIC)) - rc = -ENOMEM; - else - port->iface[if_num].alt = alt; - } else { - rc = -ENOMEM; - } - oz_complete_urb(hcd, urb, rc); -} - -/* - * Context: softirq - */ -void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, const u8 *data, - int data_len) -{ - struct oz_port *port = hport; - struct urb *urb; - struct usb_ctrlrequest *setup; - struct usb_hcd *hcd = port->ozhcd->hcd; - unsigned windex; - unsigned wvalue; - - oz_dbg(ON, "oz_hcd_control_cnf rcode=%u len=%d\n", rcode, data_len); - urb = oz_find_urb_by_id(port, 0, req_id); - if (!urb) { - oz_dbg(ON, "URB not found\n"); - return; - } - setup = (struct usb_ctrlrequest *)urb->setup_packet; - windex = le16_to_cpu(setup->wIndex); - wvalue = le16_to_cpu(setup->wValue); - if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { - /* Standard requests */ - oz_display_conf_type(setup->bRequest); - switch (setup->bRequest) { - case USB_REQ_SET_CONFIGURATION: - oz_hcd_complete_set_config(port, urb, rcode, - (u8)wvalue); - break; - case USB_REQ_SET_INTERFACE: - oz_hcd_complete_set_interface(port, urb, rcode, - (u8)windex, (u8)wvalue); - break; - default: - oz_complete_urb(hcd, urb, 0); - } - - } else { - int copy_len; - - oz_dbg(ON, "VENDOR-CLASS - cnf\n"); - if (data_len) { - if (data_len <= urb->transfer_buffer_length) - copy_len = data_len; - else - copy_len = urb->transfer_buffer_length; - memcpy(urb->transfer_buffer, data, copy_len); - urb->actual_length = copy_len; - } - oz_complete_urb(hcd, urb, 0); - } -} - -/* - * Context: softirq-serialized - */ -static int oz_hcd_buffer_data(struct oz_endpoint *ep, const u8 *data, - int data_len) -{ - int space; - int copy_len; - - if (!ep->buffer) - return -1; - space = ep->out_ix-ep->in_ix-1; - if (space < 0) - space += ep->buffer_size; - if (space < (data_len+1)) { - oz_dbg(ON, "Buffer full\n"); - return -1; - } - ep->buffer[ep->in_ix] = (u8)data_len; - if (++ep->in_ix == ep->buffer_size) - ep->in_ix = 0; - copy_len = ep->buffer_size - ep->in_ix; - if (copy_len > data_len) - copy_len = data_len; - memcpy(&ep->buffer[ep->in_ix], data, copy_len); - - if (copy_len < data_len) { - memcpy(ep->buffer, data+copy_len, data_len-copy_len); - ep->in_ix = data_len-copy_len; - } else { - ep->in_ix += copy_len; - } - if (ep->in_ix == ep->buffer_size) - ep->in_ix = 0; - ep->buffered_units++; - return 0; -} - -/* - * Context: softirq-serialized - */ -void oz_hcd_data_ind(void *hport, u8 endpoint, const u8 *data, int data_len) -{ - struct oz_port *port = (struct oz_port *)hport; - struct oz_endpoint *ep; - struct oz_hcd *ozhcd = port->ozhcd; - - spin_lock_bh(&ozhcd->hcd_lock); - ep = port->in_ep[endpoint & USB_ENDPOINT_NUMBER_MASK]; - if (ep == NULL) - goto done; - switch (ep->attrib & USB_ENDPOINT_XFERTYPE_MASK) { - case USB_ENDPOINT_XFER_INT: - case USB_ENDPOINT_XFER_BULK: - if (!list_empty(&ep->urb_list)) { - struct oz_urb_link *urbl = - list_first_entry(&ep->urb_list, - struct oz_urb_link, link); - struct urb *urb; - int copy_len; - - list_del_init(&urbl->link); - spin_unlock_bh(&ozhcd->hcd_lock); - urb = urbl->urb; - oz_free_urb_link(urbl); - if (data_len <= urb->transfer_buffer_length) - copy_len = data_len; - else - copy_len = urb->transfer_buffer_length; - memcpy(urb->transfer_buffer, data, copy_len); - urb->actual_length = copy_len; - oz_complete_urb(port->ozhcd->hcd, urb, 0); - return; - } - oz_dbg(ON, "buffering frame as URB is not available\n"); - oz_hcd_buffer_data(ep, data, data_len); - break; - case USB_ENDPOINT_XFER_ISOC: - oz_hcd_buffer_data(ep, data, data_len); - break; - } -done: - spin_unlock_bh(&ozhcd->hcd_lock); -} - -/* - * Context: unknown - */ -static inline int oz_usb_get_frame_number(void) -{ - return atomic_inc_return(&g_usb_frame_number); -} - -/* - * Context: softirq - */ -int oz_hcd_heartbeat(void *hport) -{ - int rc = 0; - struct oz_port *port = hport; - struct oz_hcd *ozhcd = port->ozhcd; - struct oz_urb_link *urbl, *n; - LIST_HEAD(xfr_list); - struct urb *urb; - struct oz_endpoint *ep; - struct timespec ts, delta; - - getrawmonotonic(&ts); - /* Check the OUT isoc endpoints to see if any URB data can be sent. - */ - spin_lock_bh(&ozhcd->hcd_lock); - list_for_each_entry(ep, &port->isoc_out_ep, link) { - if (ep->credit < 0) - continue; - delta = timespec_sub(ts, ep->timestamp); - ep->credit += div_u64(timespec_to_ns(&delta), NSEC_PER_MSEC); - if (ep->credit > ep->credit_ceiling) - ep->credit = ep->credit_ceiling; - ep->timestamp = ts; - while (ep->credit && !list_empty(&ep->urb_list)) { - urbl = list_first_entry(&ep->urb_list, - struct oz_urb_link, link); - urb = urbl->urb; - if ((ep->credit + 1) < urb->number_of_packets) - break; - ep->credit -= urb->number_of_packets; - if (ep->credit < 0) - ep->credit = 0; - list_move_tail(&urbl->link, &xfr_list); - } - } - spin_unlock_bh(&ozhcd->hcd_lock); - /* Send to PD and complete URBs. - */ - list_for_each_entry_safe(urbl, n, &xfr_list, link) { - urb = urbl->urb; - list_del_init(&urbl->link); - urb->error_count = 0; - urb->start_frame = oz_usb_get_frame_number(); - oz_usb_send_isoc(port->hpd, urbl->ep_num, urb); - oz_free_urb_link(urbl); - oz_complete_urb(port->ozhcd->hcd, urb, 0); - } - /* Check the IN isoc endpoints to see if any URBs can be completed. - */ - spin_lock_bh(&ozhcd->hcd_lock); - list_for_each_entry(ep, &port->isoc_in_ep, link) { - if (ep->flags & OZ_F_EP_BUFFERING) { - if (ep->buffered_units >= OZ_IN_BUFFERING_UNITS) { - ep->flags &= ~OZ_F_EP_BUFFERING; - ep->credit = 0; - ep->timestamp = ts; - ep->start_frame = 0; - } - continue; - } - delta = timespec_sub(ts, ep->timestamp); - ep->credit += div_u64(timespec_to_ns(&delta), NSEC_PER_MSEC); - ep->timestamp = ts; - list_for_each_entry_safe(urbl, n, &ep->urb_list, link) { - struct urb *urb = urbl->urb; - int len = 0; - int copy_len; - int i; - - if (ep->credit < urb->number_of_packets) - break; - if (ep->buffered_units < urb->number_of_packets) - break; - urb->actual_length = 0; - for (i = 0; i < urb->number_of_packets; i++) { - len = ep->buffer[ep->out_ix]; - if (++ep->out_ix == ep->buffer_size) - ep->out_ix = 0; - copy_len = ep->buffer_size - ep->out_ix; - if (copy_len > len) - copy_len = len; - memcpy(urb->transfer_buffer, - &ep->buffer[ep->out_ix], copy_len); - if (copy_len < len) { - memcpy(urb->transfer_buffer+copy_len, - ep->buffer, len-copy_len); - ep->out_ix = len-copy_len; - } else - ep->out_ix += copy_len; - if (ep->out_ix == ep->buffer_size) - ep->out_ix = 0; - urb->iso_frame_desc[i].offset = - urb->actual_length; - urb->actual_length += len; - urb->iso_frame_desc[i].actual_length = len; - urb->iso_frame_desc[i].status = 0; - } - ep->buffered_units -= urb->number_of_packets; - urb->error_count = 0; - urb->start_frame = ep->start_frame; - ep->start_frame += urb->number_of_packets; - list_move_tail(&urbl->link, &xfr_list); - ep->credit -= urb->number_of_packets; - } - } - if (!list_empty(&port->isoc_out_ep) || !list_empty(&port->isoc_in_ep)) - rc = 1; - spin_unlock_bh(&ozhcd->hcd_lock); - /* Complete the filled URBs. - */ - list_for_each_entry_safe(urbl, n, &xfr_list, link) { - urb = urbl->urb; - list_del_init(&urbl->link); - oz_free_urb_link(urbl); - oz_complete_urb(port->ozhcd->hcd, urb, 0); - } - /* Check if there are any ep0 requests that have timed out. - * If so resent to PD. - */ - ep = port->out_ep[0]; - if (ep) { - spin_lock_bh(&ozhcd->hcd_lock); - list_for_each_entry_safe(urbl, n, &ep->urb_list, link) { - if (urbl->submit_counter > EP0_TIMEOUT_COUNTER) { - oz_dbg(ON, "Request 0x%p timeout\n", urbl->urb); - list_move_tail(&urbl->link, &xfr_list); - urbl->submit_counter = 0; - } else { - urbl->submit_counter++; - } - } - if (!list_empty(&ep->urb_list)) - rc = 1; - spin_unlock_bh(&ozhcd->hcd_lock); - list_for_each_entry_safe(urbl, n, &xfr_list, link) { - oz_dbg(ON, "Resending request to PD\n"); - oz_process_ep0_urb(ozhcd, urbl->urb, GFP_ATOMIC); - oz_free_urb_link(urbl); - } - } - return rc; -} - -/* - * Context: softirq - */ -static int oz_build_endpoints_for_interface(struct usb_hcd *hcd, - struct oz_port *port, - struct usb_host_interface *intf, gfp_t mem_flags) -{ - struct oz_hcd *ozhcd = port->ozhcd; - int i; - int if_ix = intf->desc.bInterfaceNumber; - int request_heartbeat = 0; - - oz_dbg(ON, "interface[%d] = %p\n", if_ix, intf); - if (if_ix >= port->num_iface || port->iface == NULL) - return -ENOMEM; - for (i = 0; i < intf->desc.bNumEndpoints; i++) { - struct usb_host_endpoint *hep = &intf->endpoint[i]; - u8 ep_addr = hep->desc.bEndpointAddress; - u8 ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK; - struct oz_endpoint *ep; - int buffer_size = 0; - - oz_dbg(ON, "%d bEndpointAddress = %x\n", i, ep_addr); - if (ep_addr & USB_ENDPOINT_DIR_MASK) { - switch (hep->desc.bmAttributes & - USB_ENDPOINT_XFERTYPE_MASK) { - case USB_ENDPOINT_XFER_ISOC: - buffer_size = OZ_EP_BUFFER_SIZE_ISOC; - break; - case USB_ENDPOINT_XFER_INT: - buffer_size = OZ_EP_BUFFER_SIZE_INT; - break; - } - } - - ep = oz_ep_alloc(buffer_size, mem_flags); - if (!ep) { - oz_clean_endpoints_for_interface(hcd, port, if_ix); - return -ENOMEM; - } - ep->attrib = hep->desc.bmAttributes; - ep->ep_num = ep_num; - if ((ep->attrib & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_ISOC) { - oz_dbg(ON, "wMaxPacketSize = %d\n", - usb_endpoint_maxp(&hep->desc)); - ep->credit_ceiling = 200; - if (ep_addr & USB_ENDPOINT_DIR_MASK) { - ep->flags |= OZ_F_EP_BUFFERING; - } else { - ep->flags |= OZ_F_EP_HAVE_STREAM; - if (oz_usb_stream_create(port->hpd, ep_num)) - ep->flags &= ~OZ_F_EP_HAVE_STREAM; - } - } - spin_lock_bh(&ozhcd->hcd_lock); - if (ep_addr & USB_ENDPOINT_DIR_MASK) { - port->in_ep[ep_num] = ep; - port->iface[if_ix].ep_mask |= - (1<<(ep_num+OZ_NB_ENDPOINTS)); - if ((ep->attrib & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_ISOC) { - list_add_tail(&ep->link, &port->isoc_in_ep); - request_heartbeat = 1; - } - } else { - port->out_ep[ep_num] = ep; - port->iface[if_ix].ep_mask |= (1<<ep_num); - if ((ep->attrib & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_ISOC) { - list_add_tail(&ep->link, &port->isoc_out_ep); - request_heartbeat = 1; - } - } - spin_unlock_bh(&ozhcd->hcd_lock); - if (request_heartbeat && port->hpd) - oz_usb_request_heartbeat(port->hpd); - } - return 0; -} - -/* - * Context: softirq - */ -static void oz_clean_endpoints_for_interface(struct usb_hcd *hcd, - struct oz_port *port, int if_ix) -{ - struct oz_hcd *ozhcd = port->ozhcd; - unsigned mask; - int i; - LIST_HEAD(ep_list); - struct oz_endpoint *ep, *n; - - oz_dbg(ON, "Deleting endpoints for interface %d\n", if_ix); - if (if_ix >= port->num_iface) - return; - spin_lock_bh(&ozhcd->hcd_lock); - mask = port->iface[if_ix].ep_mask; - port->iface[if_ix].ep_mask = 0; - for (i = 0; i < OZ_NB_ENDPOINTS; i++) { - struct list_head *e; - /* Gather OUT endpoints. - */ - if ((mask & (1<<i)) && port->out_ep[i]) { - e = &port->out_ep[i]->link; - port->out_ep[i] = NULL; - /* Remove from isoc list if present. - */ - list_move_tail(e, &ep_list); - } - /* Gather IN endpoints. - */ - if ((mask & (1<<(i+OZ_NB_ENDPOINTS))) && port->in_ep[i]) { - e = &port->in_ep[i]->link; - port->in_ep[i] = NULL; - list_move_tail(e, &ep_list); - } - } - spin_unlock_bh(&ozhcd->hcd_lock); - list_for_each_entry_safe(ep, n, &ep_list, link) { - list_del_init(&ep->link); - oz_ep_free(port, ep); - } -} - -/* - * Context: softirq - */ -static int oz_build_endpoints_for_config(struct usb_hcd *hcd, - struct oz_port *port, struct usb_host_config *config, - gfp_t mem_flags) -{ - struct oz_hcd *ozhcd = port->ozhcd; - int i; - int num_iface = config->desc.bNumInterfaces; - - if (num_iface) { - struct oz_interface *iface; - - iface = kmalloc_array(num_iface, sizeof(struct oz_interface), - mem_flags | __GFP_ZERO); - if (!iface) - return -ENOMEM; - spin_lock_bh(&ozhcd->hcd_lock); - port->iface = iface; - port->num_iface = num_iface; - spin_unlock_bh(&ozhcd->hcd_lock); - } - for (i = 0; i < num_iface; i++) { - struct usb_host_interface *intf = - &config->intf_cache[i]->altsetting[0]; - if (oz_build_endpoints_for_interface(hcd, port, intf, - mem_flags)) - goto fail; - } - return 0; -fail: - oz_clean_endpoints_for_config(hcd, port); - return -1; -} - -/* - * Context: softirq - */ -static void oz_clean_endpoints_for_config(struct usb_hcd *hcd, - struct oz_port *port) -{ - struct oz_hcd *ozhcd = port->ozhcd; - int i; - - oz_dbg(ON, "Deleting endpoints for configuration\n"); - for (i = 0; i < port->num_iface; i++) - oz_clean_endpoints_for_interface(hcd, port, i); - spin_lock_bh(&ozhcd->hcd_lock); - if (port->iface) { - oz_dbg(ON, "Freeing interfaces object\n"); - kfree(port->iface); - port->iface = NULL; - } - port->num_iface = 0; - spin_unlock_bh(&ozhcd->hcd_lock); -} - -/* - * Context: tasklet - */ -static void *oz_claim_hpd(struct oz_port *port) -{ - void *hpd; - struct oz_hcd *ozhcd = port->ozhcd; - - spin_lock_bh(&ozhcd->hcd_lock); - hpd = port->hpd; - if (hpd) - oz_usb_get(hpd); - spin_unlock_bh(&ozhcd->hcd_lock); - return hpd; -} - -/* - * Context: tasklet - */ -static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb, - gfp_t mem_flags) -{ - struct usb_ctrlrequest *setup; - unsigned windex; - unsigned wvalue; - unsigned wlength; - void *hpd; - u8 req_id; - int rc = 0; - unsigned complete = 0; - - int port_ix = -1; - struct oz_port *port = NULL; - - oz_dbg(URB, "[%s]:(%p)\n", __func__, urb); - port_ix = oz_get_port_from_addr(ozhcd, urb->dev->devnum); - if (port_ix < 0) { - rc = -EPIPE; - goto out; - } - port = &ozhcd->ports[port_ix]; - if (((port->flags & OZ_PORT_F_PRESENT) == 0) - || (port->flags & OZ_PORT_F_DYING)) { - oz_dbg(ON, "Refusing URB port_ix = %d devnum = %d\n", - port_ix, urb->dev->devnum); - rc = -EPIPE; - goto out; - } - /* Store port in private context data. - */ - urb->hcpriv = port; - setup = (struct usb_ctrlrequest *)urb->setup_packet; - windex = le16_to_cpu(setup->wIndex); - wvalue = le16_to_cpu(setup->wValue); - wlength = le16_to_cpu(setup->wLength); - oz_dbg(CTRL_DETAIL, "bRequestType = %x\n", setup->bRequestType); - oz_dbg(CTRL_DETAIL, "bRequest = %x\n", setup->bRequest); - oz_dbg(CTRL_DETAIL, "wValue = %x\n", wvalue); - oz_dbg(CTRL_DETAIL, "wIndex = %x\n", windex); - oz_dbg(CTRL_DETAIL, "wLength = %x\n", wlength); - - req_id = port->next_req_id++; - hpd = oz_claim_hpd(port); - if (hpd == NULL) { - oz_dbg(ON, "Cannot claim port\n"); - rc = -EPIPE; - goto out; - } - - if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { - /* Standard requests - */ - switch (setup->bRequest) { - case USB_REQ_GET_DESCRIPTOR: - oz_dbg(ON, "USB_REQ_GET_DESCRIPTOR - req\n"); - break; - case USB_REQ_SET_ADDRESS: - oz_dbg(ON, "USB_REQ_SET_ADDRESS - req\n"); - oz_dbg(ON, "Port %d address is 0x%x\n", - ozhcd->conn_port, - (u8)le16_to_cpu(setup->wValue)); - spin_lock_bh(&ozhcd->hcd_lock); - if (ozhcd->conn_port >= 0) { - ozhcd->ports[ozhcd->conn_port].bus_addr = - (u8)le16_to_cpu(setup->wValue); - oz_dbg(ON, "Clearing conn_port\n"); - ozhcd->conn_port = -1; - } - spin_unlock_bh(&ozhcd->hcd_lock); - complete = 1; - break; - case USB_REQ_SET_CONFIGURATION: - oz_dbg(ON, "USB_REQ_SET_CONFIGURATION - req\n"); - break; - case USB_REQ_GET_CONFIGURATION: - /* We short circuit this case and reply directly since - * we have the selected configuration number cached. - */ - oz_dbg(ON, "USB_REQ_GET_CONFIGURATION - reply now\n"); - if (urb->transfer_buffer_length >= 1) { - urb->actual_length = 1; - *((u8 *)urb->transfer_buffer) = - port->config_num; - complete = 1; - } else { - rc = -EPIPE; - } - break; - case USB_REQ_GET_INTERFACE: - /* We short circuit this case and reply directly since - * we have the selected interface alternative cached. - */ - oz_dbg(ON, "USB_REQ_GET_INTERFACE - reply now\n"); - if (urb->transfer_buffer_length >= 1) { - urb->actual_length = 1; - *((u8 *)urb->transfer_buffer) = - port->iface[(u8)windex].alt; - oz_dbg(ON, "interface = %d alt = %d\n", - windex, port->iface[(u8)windex].alt); - complete = 1; - } else { - rc = -EPIPE; - } - break; - case USB_REQ_SET_INTERFACE: - oz_dbg(ON, "USB_REQ_SET_INTERFACE - req\n"); - break; - } - } - if (!rc && !complete) { - int data_len = 0; - - if ((setup->bRequestType & USB_DIR_IN) == 0) - data_len = wlength; - urb->actual_length = data_len; - if (oz_usb_control_req(port->hpd, req_id, setup, - urb->transfer_buffer, data_len)) { - rc = -ENOMEM; - } else { - /* Note: we are queuing the request after we have - * submitted it to be transmitted. If the request were - * to complete before we queued it then it would not - * be found in the queue. It seems impossible for - * this to happen but if it did the request would - * be resubmitted so the problem would hopefully - * resolve itself. Putting the request into the - * queue before it has been sent is worse since the - * urb could be cancelled while we are using it - * to build the request. - */ - if (oz_enqueue_ep_urb(port, 0, 0, urb, req_id)) - rc = -ENOMEM; - } - } - oz_usb_put(hpd); -out: - if (rc || complete) { - oz_dbg(ON, "Completing request locally\n"); - oz_complete_urb(ozhcd->hcd, urb, rc); - } else { - oz_usb_request_heartbeat(port->hpd); - } -} - -/* - * Context: tasklet - */ -static int oz_urb_process(struct oz_hcd *ozhcd, struct urb *urb) -{ - int rc = 0; - struct oz_port *port = urb->hcpriv; - u8 ep_addr; - - /* When we are paranoid we keep a list of urbs which we check against - * before handing one back. This is just for debugging during - * development and should be turned off in the released driver. - */ - oz_remember_urb(urb); - /* Check buffer is valid. - */ - if (!urb->transfer_buffer && urb->transfer_buffer_length) - return -EINVAL; - /* Check if there is a device at the port - refuse if not. - */ - if ((port->flags & OZ_PORT_F_PRESENT) == 0) - return -EPIPE; - ep_addr = usb_pipeendpoint(urb->pipe); - if (ep_addr) { - /* If the request is not for EP0 then queue it. - */ - if (oz_enqueue_ep_urb(port, ep_addr, usb_pipein(urb->pipe), - urb, 0)) - rc = -EPIPE; - } else { - oz_process_ep0_urb(ozhcd, urb, GFP_ATOMIC); - } - return rc; -} - -/* - * Context: tasklet - */ -static void oz_urb_process_tasklet(unsigned long unused) -{ - unsigned long irq_state; - struct urb *urb; - struct oz_hcd *ozhcd = oz_hcd_claim(); - struct oz_urb_link *urbl, *n; - int rc = 0; - - if (ozhcd == NULL) - return; - /* This is called from a tasklet so is in softirq context but the urb - * list is filled from any context so we need to lock - * appropriately while removing urbs. - */ - spin_lock_irqsave(&g_tasklet_lock, irq_state); - list_for_each_entry_safe(urbl, n, &ozhcd->urb_pending_list, link) { - list_del_init(&urbl->link); - spin_unlock_irqrestore(&g_tasklet_lock, irq_state); - urb = urbl->urb; - oz_free_urb_link(urbl); - rc = oz_urb_process(ozhcd, urb); - if (rc) - oz_complete_urb(ozhcd->hcd, urb, rc); - spin_lock_irqsave(&g_tasklet_lock, irq_state); - } - spin_unlock_irqrestore(&g_tasklet_lock, irq_state); - oz_hcd_put(ozhcd); -} - -/* - * This function searches for the urb in any of the lists it could be in. - * If it is found it is removed from the list and completed. If the urb is - * being processed then it won't be in a list so won't be found. However, the - * call to usb_hcd_check_unlink_urb() will set the value of the unlinked field - * to a non-zero value. When an attempt is made to put the urb back in a list - * the unlinked field will be checked and the urb will then be completed. - * Context: tasklet - */ -static void oz_urb_cancel(struct oz_port *port, u8 ep_num, struct urb *urb) -{ - struct oz_urb_link *urbl = NULL; - struct list_head *e; - struct oz_hcd *ozhcd; - unsigned long irq_state; - u8 ix; - - if (port == NULL) { - oz_dbg(ON, "%s: ERROR: (%p) port is null\n", __func__, urb); - return; - } - ozhcd = port->ozhcd; - if (ozhcd == NULL) { - oz_dbg(ON, "%s; ERROR: (%p) ozhcd is null\n", __func__, urb); - return; - } - - /* Look in the tasklet queue. - */ - spin_lock_irqsave(&g_tasklet_lock, irq_state); - list_for_each(e, &ozhcd->urb_cancel_list) { - urbl = list_entry(e, struct oz_urb_link, link); - if (urb == urbl->urb) { - list_del_init(e); - spin_unlock_irqrestore(&g_tasklet_lock, irq_state); - goto out2; - } - } - spin_unlock_irqrestore(&g_tasklet_lock, irq_state); - urbl = NULL; - - /* Look in the orphanage. - */ - spin_lock_irqsave(&ozhcd->hcd_lock, irq_state); - list_for_each(e, &ozhcd->orphanage) { - urbl = list_entry(e, struct oz_urb_link, link); - if (urbl->urb == urb) { - list_del(e); - oz_dbg(ON, "Found urb in orphanage\n"); - goto out; - } - } - ix = (ep_num & 0xf); - urbl = NULL; - if ((ep_num & USB_DIR_IN) && ix) - urbl = oz_remove_urb(port->in_ep[ix], urb); - else - urbl = oz_remove_urb(port->out_ep[ix], urb); -out: - spin_unlock_irqrestore(&ozhcd->hcd_lock, irq_state); -out2: - if (urbl) { - urb->actual_length = 0; - oz_free_urb_link(urbl); - oz_complete_urb(ozhcd->hcd, urb, -EPIPE); - } -} - -/* - * Context: tasklet - */ -static void oz_urb_cancel_tasklet(unsigned long unused) -{ - unsigned long irq_state; - struct urb *urb; - struct oz_urb_link *urbl, *n; - struct oz_hcd *ozhcd = oz_hcd_claim(); - - if (ozhcd == NULL) - return; - spin_lock_irqsave(&g_tasklet_lock, irq_state); - list_for_each_entry_safe(urbl, n, &ozhcd->urb_cancel_list, link) { - list_del_init(&urbl->link); - spin_unlock_irqrestore(&g_tasklet_lock, irq_state); - urb = urbl->urb; - if (urb->unlinked) - oz_urb_cancel(urbl->port, urbl->ep_num, urb); - oz_free_urb_link(urbl); - spin_lock_irqsave(&g_tasklet_lock, irq_state); - } - spin_unlock_irqrestore(&g_tasklet_lock, irq_state); - oz_hcd_put(ozhcd); -} - -/* - * Context: unknown - */ -static void oz_hcd_clear_orphanage(struct oz_hcd *ozhcd, int status) -{ - if (ozhcd) { - struct oz_urb_link *urbl, *n; - - list_for_each_entry_safe(urbl, n, &ozhcd->orphanage, link) { - list_del(&urbl->link); - oz_complete_urb(ozhcd->hcd, urbl->urb, status); - oz_free_urb_link(urbl); - } - } -} - -/* - * Context: unknown - */ -static int oz_hcd_start(struct usb_hcd *hcd) -{ - hcd->power_budget = 200; - hcd->state = HC_STATE_RUNNING; - hcd->uses_new_polling = 1; - return 0; -} - -/* - * Context: unknown - */ -static void oz_hcd_stop(struct usb_hcd *hcd) -{ -} - -/* - * Context: unknown - */ -static void oz_hcd_shutdown(struct usb_hcd *hcd) -{ -} - -/* - * Called to queue an urb for the device. - * This function should return a non-zero error code if it fails the urb but - * should not call usb_hcd_giveback_urb(). - * Context: any - */ -static int oz_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, - gfp_t mem_flags) -{ - struct oz_hcd *ozhcd = oz_hcd_private(hcd); - int rc; - int port_ix; - struct oz_port *port; - unsigned long irq_state; - struct oz_urb_link *urbl; - - oz_dbg(URB, "%s: (%p)\n", __func__, urb); - if (unlikely(ozhcd == NULL)) { - oz_dbg(URB, "Refused urb(%p) not ozhcd\n", urb); - return -EPIPE; - } - if (unlikely(hcd->state != HC_STATE_RUNNING)) { - oz_dbg(URB, "Refused urb(%p) not running\n", urb); - return -EPIPE; - } - port_ix = oz_get_port_from_addr(ozhcd, urb->dev->devnum); - if (port_ix < 0) - return -EPIPE; - port = &ozhcd->ports[port_ix]; - if (port == NULL) - return -EPIPE; - if (!(port->flags & OZ_PORT_F_PRESENT) || - (port->flags & OZ_PORT_F_CHANGED)) { - oz_dbg(ON, "Refusing URB port_ix = %d devnum = %d\n", - port_ix, urb->dev->devnum); - return -EPIPE; - } - urb->hcpriv = port; - /* Put request in queue for processing by tasklet. - */ - urbl = oz_alloc_urb_link(); - if (unlikely(urbl == NULL)) - return -ENOMEM; - urbl->urb = urb; - spin_lock_irqsave(&g_tasklet_lock, irq_state); - rc = usb_hcd_link_urb_to_ep(hcd, urb); - if (unlikely(rc)) { - spin_unlock_irqrestore(&g_tasklet_lock, irq_state); - oz_free_urb_link(urbl); - return rc; - } - list_add_tail(&urbl->link, &ozhcd->urb_pending_list); - spin_unlock_irqrestore(&g_tasklet_lock, irq_state); - tasklet_schedule(&g_urb_process_tasklet); - atomic_inc(&g_pending_urbs); - return 0; -} - -/* - * Context: tasklet - */ -static struct oz_urb_link *oz_remove_urb(struct oz_endpoint *ep, - struct urb *urb) -{ - struct oz_urb_link *urbl; - - if (unlikely(ep == NULL)) - return NULL; - - list_for_each_entry(urbl, &ep->urb_list, link) { - if (urbl->urb == urb) { - list_del_init(&urbl->link); - if (usb_pipeisoc(urb->pipe)) { - ep->credit -= urb->number_of_packets; - if (ep->credit < 0) - ep->credit = 0; - } - return urbl; - } - } - return NULL; -} - -/* - * Called to dequeue a previously submitted urb for the device. - * Context: any - */ -static int oz_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) -{ - struct oz_hcd *ozhcd = oz_hcd_private(hcd); - struct oz_urb_link *urbl; - int rc; - unsigned long irq_state; - - oz_dbg(URB, "%s: (%p)\n", __func__, urb); - urbl = oz_alloc_urb_link(); - if (unlikely(urbl == NULL)) - return -ENOMEM; - spin_lock_irqsave(&g_tasklet_lock, irq_state); - /* The following function checks the urb is still in the queue - * maintained by the core and that the unlinked field is zero. - * If both are true the function sets the unlinked field and returns - * zero. Otherwise it returns an error. - */ - rc = usb_hcd_check_unlink_urb(hcd, urb, status); - /* We have to check we haven't completed the urb or are about - * to complete it. When we do we set hcpriv to 0 so if this has - * already happened we don't put the urb in the cancel queue. - */ - if ((rc == 0) && urb->hcpriv) { - urbl->urb = urb; - urbl->port = (struct oz_port *)urb->hcpriv; - urbl->ep_num = usb_pipeendpoint(urb->pipe); - if (usb_pipein(urb->pipe)) - urbl->ep_num |= USB_DIR_IN; - list_add_tail(&urbl->link, &ozhcd->urb_cancel_list); - spin_unlock_irqrestore(&g_tasklet_lock, irq_state); - tasklet_schedule(&g_urb_cancel_tasklet); - } else { - spin_unlock_irqrestore(&g_tasklet_lock, irq_state); - oz_free_urb_link(urbl); - } - return rc; -} - -/* - * Context: unknown - */ -static void oz_hcd_endpoint_disable(struct usb_hcd *hcd, - struct usb_host_endpoint *ep) -{ -} - -/* - * Context: unknown - */ -static void oz_hcd_endpoint_reset(struct usb_hcd *hcd, - struct usb_host_endpoint *ep) -{ -} - -/* - * Context: unknown - */ -static int oz_hcd_get_frame_number(struct usb_hcd *hcd) -{ - oz_dbg(ON, "oz_hcd_get_frame_number\n"); - return oz_usb_get_frame_number(); -} - -/* - * Context: softirq - * This is called as a consquence of us calling usb_hcd_poll_rh_status() and we - * always do that in softirq context. - */ -static int oz_hcd_hub_status_data(struct usb_hcd *hcd, char *buf) -{ - struct oz_hcd *ozhcd = oz_hcd_private(hcd); - int i; - - buf[0] = 0; - buf[1] = 0; - - spin_lock_bh(&ozhcd->hcd_lock); - for (i = 0; i < OZ_NB_PORTS; i++) { - if (ozhcd->ports[i].flags & OZ_PORT_F_CHANGED) { - oz_dbg(HUB, "Port %d changed\n", i); - ozhcd->ports[i].flags &= ~OZ_PORT_F_CHANGED; - if (i < 7) - buf[0] |= 1 << (i + 1); - else - buf[1] |= 1 << (i - 7); - } - } - spin_unlock_bh(&ozhcd->hcd_lock); - if (buf[0] != 0 || buf[1] != 0) - return 2; - return 0; -} - -/* - * Context: process - */ -static void oz_get_hub_descriptor(struct usb_hcd *hcd, - struct usb_hub_descriptor *desc) -{ - memset(desc, 0, sizeof(*desc)); - desc->bDescriptorType = 0x29; - desc->bDescLength = 9; - desc->wHubCharacteristics = cpu_to_le16(0x0001); - desc->bNbrPorts = OZ_NB_PORTS; -} - -/* - * Context: process - */ -static int oz_set_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex) -{ - struct oz_port *port; - u8 port_id = (u8)windex; - struct oz_hcd *ozhcd = oz_hcd_private(hcd); - unsigned set_bits = 0; - unsigned clear_bits = 0; - - if ((port_id < 1) || (port_id > OZ_NB_PORTS)) - return -EPIPE; - port = &ozhcd->ports[port_id-1]; - switch (wvalue) { - case USB_PORT_FEAT_CONNECTION: - oz_dbg(HUB, "USB_PORT_FEAT_CONNECTION\n"); - break; - case USB_PORT_FEAT_ENABLE: - oz_dbg(HUB, "USB_PORT_FEAT_ENABLE\n"); - break; - case USB_PORT_FEAT_SUSPEND: - oz_dbg(HUB, "USB_PORT_FEAT_SUSPEND\n"); - break; - case USB_PORT_FEAT_OVER_CURRENT: - oz_dbg(HUB, "USB_PORT_FEAT_OVER_CURRENT\n"); - break; - case USB_PORT_FEAT_RESET: - oz_dbg(HUB, "USB_PORT_FEAT_RESET\n"); - set_bits = USB_PORT_STAT_ENABLE | (USB_PORT_STAT_C_RESET<<16); - clear_bits = USB_PORT_STAT_RESET; - ozhcd->ports[port_id-1].bus_addr = 0; - break; - case USB_PORT_FEAT_POWER: - oz_dbg(HUB, "USB_PORT_FEAT_POWER\n"); - set_bits |= USB_PORT_STAT_POWER; - break; - case USB_PORT_FEAT_LOWSPEED: - oz_dbg(HUB, "USB_PORT_FEAT_LOWSPEED\n"); - break; - case USB_PORT_FEAT_C_CONNECTION: - oz_dbg(HUB, "USB_PORT_FEAT_C_CONNECTION\n"); - break; - case USB_PORT_FEAT_C_ENABLE: - oz_dbg(HUB, "USB_PORT_FEAT_C_ENABLE\n"); - break; - case USB_PORT_FEAT_C_SUSPEND: - oz_dbg(HUB, "USB_PORT_FEAT_C_SUSPEND\n"); - break; - case USB_PORT_FEAT_C_OVER_CURRENT: - oz_dbg(HUB, "USB_PORT_FEAT_C_OVER_CURRENT\n"); - break; - case USB_PORT_FEAT_C_RESET: - oz_dbg(HUB, "USB_PORT_FEAT_C_RESET\n"); - break; - case USB_PORT_FEAT_TEST: - oz_dbg(HUB, "USB_PORT_FEAT_TEST\n"); - break; - case USB_PORT_FEAT_INDICATOR: - oz_dbg(HUB, "USB_PORT_FEAT_INDICATOR\n"); - break; - default: - oz_dbg(HUB, "Other %d\n", wvalue); - break; - } - if (set_bits || clear_bits) { - spin_lock_bh(&port->port_lock); - port->status &= ~clear_bits; - port->status |= set_bits; - spin_unlock_bh(&port->port_lock); - } - oz_dbg(HUB, "Port[%d] status = 0x%x\n", port_id, port->status); - return 0; -} - -/* - * Context: process - */ -static int oz_clear_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex) -{ - struct oz_port *port; - u8 port_id = (u8)windex; - struct oz_hcd *ozhcd = oz_hcd_private(hcd); - unsigned clear_bits = 0; - - if ((port_id < 1) || (port_id > OZ_NB_PORTS)) - return -EPIPE; - port = &ozhcd->ports[port_id-1]; - switch (wvalue) { - case USB_PORT_FEAT_CONNECTION: - oz_dbg(HUB, "USB_PORT_FEAT_CONNECTION\n"); - break; - case USB_PORT_FEAT_ENABLE: - oz_dbg(HUB, "USB_PORT_FEAT_ENABLE\n"); - clear_bits = USB_PORT_STAT_ENABLE; - break; - case USB_PORT_FEAT_SUSPEND: - oz_dbg(HUB, "USB_PORT_FEAT_SUSPEND\n"); - break; - case USB_PORT_FEAT_OVER_CURRENT: - oz_dbg(HUB, "USB_PORT_FEAT_OVER_CURRENT\n"); - break; - case USB_PORT_FEAT_RESET: - oz_dbg(HUB, "USB_PORT_FEAT_RESET\n"); - break; - case USB_PORT_FEAT_POWER: - oz_dbg(HUB, "USB_PORT_FEAT_POWER\n"); - clear_bits |= USB_PORT_STAT_POWER; - break; - case USB_PORT_FEAT_LOWSPEED: - oz_dbg(HUB, "USB_PORT_FEAT_LOWSPEED\n"); - break; - case USB_PORT_FEAT_C_CONNECTION: - oz_dbg(HUB, "USB_PORT_FEAT_C_CONNECTION\n"); - clear_bits = USB_PORT_STAT_C_CONNECTION << 16; - break; - case USB_PORT_FEAT_C_ENABLE: - oz_dbg(HUB, "USB_PORT_FEAT_C_ENABLE\n"); - clear_bits = USB_PORT_STAT_C_ENABLE << 16; - break; - case USB_PORT_FEAT_C_SUSPEND: - oz_dbg(HUB, "USB_PORT_FEAT_C_SUSPEND\n"); - break; - case USB_PORT_FEAT_C_OVER_CURRENT: - oz_dbg(HUB, "USB_PORT_FEAT_C_OVER_CURRENT\n"); - break; - case USB_PORT_FEAT_C_RESET: - oz_dbg(HUB, "USB_PORT_FEAT_C_RESET\n"); - clear_bits = USB_PORT_FEAT_C_RESET << 16; - break; - case USB_PORT_FEAT_TEST: - oz_dbg(HUB, "USB_PORT_FEAT_TEST\n"); - break; - case USB_PORT_FEAT_INDICATOR: - oz_dbg(HUB, "USB_PORT_FEAT_INDICATOR\n"); - break; - default: - oz_dbg(HUB, "Other %d\n", wvalue); - break; - } - if (clear_bits) { - spin_lock_bh(&port->port_lock); - port->status &= ~clear_bits; - spin_unlock_bh(&port->port_lock); - } - oz_dbg(HUB, "Port[%d] status = 0x%x\n", - port_id, ozhcd->ports[port_id-1].status); - return 0; -} - -/* - * Context: process - */ -static int oz_get_port_status(struct usb_hcd *hcd, u16 windex, char *buf) -{ - struct oz_hcd *ozhcd; - u32 status; - - if ((windex < 1) || (windex > OZ_NB_PORTS)) - return -EPIPE; - ozhcd = oz_hcd_private(hcd); - oz_dbg(HUB, "GetPortStatus windex = %d\n", windex); - status = ozhcd->ports[windex-1].status; - put_unaligned(cpu_to_le32(status), (__le32 *)buf); - oz_dbg(HUB, "Port[%d] status = %x\n", windex, status); - return 0; -} - -/* - * Context: process - */ -static int oz_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 wvalue, - u16 windex, char *buf, u16 wlength) -{ - int err = 0; - - switch (req_type) { - case ClearHubFeature: - oz_dbg(HUB, "ClearHubFeature: %d\n", req_type); - break; - case ClearPortFeature: - err = oz_clear_port_feature(hcd, wvalue, windex); - break; - case GetHubDescriptor: - oz_get_hub_descriptor(hcd, (struct usb_hub_descriptor *)buf); - break; - case GetHubStatus: - oz_dbg(HUB, "GetHubStatus: req_type = 0x%x\n", req_type); - put_unaligned(cpu_to_le32(0), (__le32 *)buf); - break; - case GetPortStatus: - err = oz_get_port_status(hcd, windex, buf); - break; - case SetHubFeature: - oz_dbg(HUB, "SetHubFeature: %d\n", req_type); - break; - case SetPortFeature: - err = oz_set_port_feature(hcd, wvalue, windex); - break; - default: - oz_dbg(HUB, "Other: %d\n", req_type); - break; - } - return err; -} - -/* - * Context: process - */ -static int oz_hcd_bus_suspend(struct usb_hcd *hcd) -{ - struct oz_hcd *ozhcd; - - ozhcd = oz_hcd_private(hcd); - spin_lock_bh(&ozhcd->hcd_lock); - hcd->state = HC_STATE_SUSPENDED; - ozhcd->flags |= OZ_HDC_F_SUSPENDED; - spin_unlock_bh(&ozhcd->hcd_lock); - return 0; -} - -/* - * Context: process - */ -static int oz_hcd_bus_resume(struct usb_hcd *hcd) -{ - struct oz_hcd *ozhcd; - - ozhcd = oz_hcd_private(hcd); - spin_lock_bh(&ozhcd->hcd_lock); - ozhcd->flags &= ~OZ_HDC_F_SUSPENDED; - hcd->state = HC_STATE_RUNNING; - spin_unlock_bh(&ozhcd->hcd_lock); - return 0; -} - -static void oz_plat_shutdown(struct platform_device *dev) -{ -} - -/* - * Context: process - */ -static int oz_plat_probe(struct platform_device *dev) -{ - int i; - int err; - struct usb_hcd *hcd; - struct oz_hcd *ozhcd; - - hcd = usb_create_hcd(&g_oz_hc_drv, &dev->dev, dev_name(&dev->dev)); - if (hcd == NULL) { - oz_dbg(ON, "Failed to created hcd object OK\n"); - return -ENOMEM; - } - ozhcd = oz_hcd_private(hcd); - memset(ozhcd, 0, sizeof(*ozhcd)); - INIT_LIST_HEAD(&ozhcd->urb_pending_list); - INIT_LIST_HEAD(&ozhcd->urb_cancel_list); - INIT_LIST_HEAD(&ozhcd->orphanage); - ozhcd->hcd = hcd; - ozhcd->conn_port = -1; - spin_lock_init(&ozhcd->hcd_lock); - for (i = 0; i < OZ_NB_PORTS; i++) { - struct oz_port *port = &ozhcd->ports[i]; - - port->ozhcd = ozhcd; - port->flags = 0; - port->status = 0; - port->bus_addr = 0xff; - spin_lock_init(&port->port_lock); - } - err = usb_add_hcd(hcd, 0, 0); - if (err) { - oz_dbg(ON, "Failed to add hcd object OK\n"); - usb_put_hcd(hcd); - return -1; - } - device_wakeup_enable(hcd->self.controller); - - spin_lock_bh(&g_hcdlock); - g_ozhcd = ozhcd; - spin_unlock_bh(&g_hcdlock); - return 0; -} - -/* - * Context: unknown - */ -static int oz_plat_remove(struct platform_device *dev) -{ - struct usb_hcd *hcd = platform_get_drvdata(dev); - struct oz_hcd *ozhcd; - - if (hcd == NULL) - return -1; - ozhcd = oz_hcd_private(hcd); - spin_lock_bh(&g_hcdlock); - if (ozhcd == g_ozhcd) - g_ozhcd = NULL; - spin_unlock_bh(&g_hcdlock); - oz_dbg(ON, "Clearing orphanage\n"); - oz_hcd_clear_orphanage(ozhcd, -EPIPE); - oz_dbg(ON, "Removing hcd\n"); - usb_remove_hcd(hcd); - usb_put_hcd(hcd); - return 0; -} - -/* - * Context: unknown - */ -static int oz_plat_suspend(struct platform_device *dev, pm_message_t msg) -{ - return 0; -} - - -/* - * Context: unknown - */ -static int oz_plat_resume(struct platform_device *dev) -{ - return 0; -} - -/* - * Context: process - */ -int oz_hcd_init(void) -{ - int err; - - if (usb_disabled()) - return -ENODEV; - - oz_urb_link_cache = KMEM_CACHE(oz_urb_link, 0); - if (!oz_urb_link_cache) - return -ENOMEM; - - tasklet_init(&g_urb_process_tasklet, oz_urb_process_tasklet, 0); - tasklet_init(&g_urb_cancel_tasklet, oz_urb_cancel_tasklet, 0); - err = platform_driver_register(&g_oz_plat_drv); - oz_dbg(ON, "platform_driver_register() returned %d\n", err); - if (err) - goto error; - g_plat_dev = platform_device_alloc(OZ_PLAT_DEV_NAME, -1); - if (g_plat_dev == NULL) { - err = -ENOMEM; - goto error1; - } - oz_dbg(ON, "platform_device_alloc() succeeded\n"); - err = platform_device_add(g_plat_dev); - if (err) - goto error2; - oz_dbg(ON, "platform_device_add() succeeded\n"); - return 0; -error2: - platform_device_put(g_plat_dev); -error1: - platform_driver_unregister(&g_oz_plat_drv); -error: - tasklet_disable(&g_urb_process_tasklet); - tasklet_disable(&g_urb_cancel_tasklet); - oz_dbg(ON, "oz_hcd_init() failed %d\n", err); - return err; -} - -/* - * Context: process - */ -void oz_hcd_term(void) -{ - msleep(OZ_HUB_DEBOUNCE_TIMEOUT); - tasklet_kill(&g_urb_process_tasklet); - tasklet_kill(&g_urb_cancel_tasklet); - platform_device_unregister(g_plat_dev); - platform_driver_unregister(&g_oz_plat_drv); - oz_dbg(ON, "Pending urbs:%d\n", atomic_read(&g_pending_urbs)); - kmem_cache_destroy(oz_urb_link_cache); -} diff --git a/drivers/staging/ozwpan/ozhcd.h b/drivers/staging/ozwpan/ozhcd.h deleted file mode 100644 index 55e97b1c7079..000000000000 --- a/drivers/staging/ozwpan/ozhcd.h +++ /dev/null @@ -1,15 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * ---------------------------------------------------------------------------*/ -#ifndef _OZHCD_H -#define _OZHCD_H - -int oz_hcd_init(void); -void oz_hcd_term(void); -struct oz_port *oz_hcd_pd_arrived(void *ctx); -void oz_hcd_pd_departed(struct oz_port *hport); -void oz_hcd_pd_reset(void *hpd, void *hport); - -#endif /* _OZHCD_H */ - diff --git a/drivers/staging/ozwpan/ozmain.c b/drivers/staging/ozwpan/ozmain.c deleted file mode 100644 index 74ef34815b98..000000000000 --- a/drivers/staging/ozwpan/ozmain.c +++ /dev/null @@ -1,71 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * ----------------------------------------------------------------------------- - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/timer.h> -#include <linux/sched.h> -#include <linux/netdevice.h> -#include <linux/errno.h> -#include <linux/ieee80211.h> -#include "ozdbg.h" -#include "ozpd.h" -#include "ozproto.h" -#include "ozcdev.h" - -unsigned int oz_dbg_mask = OZ_DEFAULT_DBG_MASK; - -/* - * The name of the 802.11 mac device. Empty string is the default value but a - * value can be supplied as a parameter to the module. An empty string means - * bind to nothing. '*' means bind to all netcards - this includes non-802.11 - * netcards. Bindings can be added later using an IOCTL. - */ -static char *g_net_dev = ""; -module_param(g_net_dev, charp, S_IRUGO); -MODULE_PARM_DESC(g_net_dev, "The device(s) to bind to; " - "'*' means all, '' (empty string; default) means none."); - -/* - * Context: process - */ -static int __init ozwpan_init(void) -{ - int err; - - err = oz_cdev_register(); - if (err) - return err; - err = oz_protocol_init(g_net_dev); - if (err) - goto err_protocol; - oz_app_enable(OZ_APPID_USB, 1); - oz_apps_init(); - return 0; - -err_protocol: - oz_cdev_deregister(); - return err; -} - -/* - * Context: process - */ -static void __exit ozwpan_exit(void) -{ - oz_protocol_term(); - oz_apps_term(); - oz_cdev_deregister(); -} - -module_init(ozwpan_init); -module_exit(ozwpan_exit); - -MODULE_AUTHOR("Chris Kelly"); -MODULE_DESCRIPTION("Ozmo Devices USB over WiFi hcd driver"); -MODULE_VERSION("1.0.13"); -MODULE_LICENSE("GPL"); - diff --git a/drivers/staging/ozwpan/ozpd.c b/drivers/staging/ozwpan/ozpd.c deleted file mode 100644 index 021d74a132dd..000000000000 --- a/drivers/staging/ozwpan/ozpd.c +++ /dev/null @@ -1,886 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * ----------------------------------------------------------------------------- - */ - -#include <linux/module.h> -#include <linux/timer.h> -#include <linux/sched.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/errno.h> -#include "ozdbg.h" -#include "ozprotocol.h" -#include "ozeltbuf.h" -#include "ozpd.h" -#include "ozproto.h" -#include "ozcdev.h" -#include "ozusbsvc.h" -#include <asm/unaligned.h> -#include <linux/uaccess.h> -#include <net/psnap.h> - -static struct oz_tx_frame *oz_tx_frame_alloc(struct oz_pd *pd); -static void oz_tx_frame_free(struct oz_pd *pd, struct oz_tx_frame *f); -static void oz_tx_isoc_free(struct oz_pd *pd, struct oz_tx_frame *f); -static struct sk_buff *oz_build_frame(struct oz_pd *pd, struct oz_tx_frame *f); -static int oz_send_isoc_frame(struct oz_pd *pd); -static void oz_retire_frame(struct oz_pd *pd, struct oz_tx_frame *f); -static void oz_isoc_stream_free(struct oz_isoc_stream *st); -static int oz_send_next_queued_frame(struct oz_pd *pd, int more_data); -static void oz_isoc_destructor(struct sk_buff *skb); - -/* - * Counts the uncompleted isoc frames submitted to netcard. - */ -static atomic_t g_submitted_isoc = ATOMIC_INIT(0); - -/* Application handler functions. - */ -static const struct oz_app_if g_app_if[OZ_NB_APPS] = { - [OZ_APPID_USB] = { - .init = oz_usb_init, - .term = oz_usb_term, - .start = oz_usb_start, - .stop = oz_usb_stop, - .rx = oz_usb_rx, - .heartbeat = oz_usb_heartbeat, - .farewell = oz_usb_farewell, - }, - [OZ_APPID_SERIAL] = { - .init = oz_cdev_init, - .term = oz_cdev_term, - .start = oz_cdev_start, - .stop = oz_cdev_stop, - .rx = oz_cdev_rx, - }, -}; - - -/* - * Context: softirq or process - */ -void oz_pd_set_state(struct oz_pd *pd, unsigned state) -{ - pd->state = state; - switch (state) { - case OZ_PD_S_IDLE: - oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_IDLE\n"); - break; - case OZ_PD_S_CONNECTED: - oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_CONNECTED\n"); - break; - case OZ_PD_S_STOPPED: - oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_STOPPED\n"); - break; - case OZ_PD_S_SLEEP: - oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_SLEEP\n"); - break; - } -} - -/* - * Context: softirq or process - */ -void oz_pd_get(struct oz_pd *pd) -{ - atomic_inc(&pd->ref_count); -} - -/* - * Context: softirq or process - */ -void oz_pd_put(struct oz_pd *pd) -{ - if (atomic_dec_and_test(&pd->ref_count)) - oz_pd_destroy(pd); -} - -/* - * Context: softirq-serialized - */ -struct oz_pd *oz_pd_alloc(const u8 *mac_addr) -{ - struct oz_pd *pd; - int i; - - pd = kzalloc(sizeof(struct oz_pd), GFP_ATOMIC); - if (!pd) - return NULL; - - atomic_set(&pd->ref_count, 2); - for (i = 0; i < OZ_NB_APPS; i++) - spin_lock_init(&pd->app_lock[i]); - pd->last_rx_pkt_num = 0xffffffff; - oz_pd_set_state(pd, OZ_PD_S_IDLE); - pd->max_tx_size = OZ_MAX_TX_SIZE; - ether_addr_copy(pd->mac_addr, mac_addr); - oz_elt_buf_init(&pd->elt_buff); - spin_lock_init(&pd->tx_frame_lock); - INIT_LIST_HEAD(&pd->tx_queue); - INIT_LIST_HEAD(&pd->farewell_list); - pd->last_sent_frame = &pd->tx_queue; - spin_lock_init(&pd->stream_lock); - INIT_LIST_HEAD(&pd->stream_list); - tasklet_init(&pd->heartbeat_tasklet, oz_pd_heartbeat_handler, - (unsigned long)pd); - tasklet_init(&pd->timeout_tasklet, oz_pd_timeout_handler, - (unsigned long)pd); - hrtimer_init(&pd->heartbeat, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - hrtimer_init(&pd->timeout, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - pd->heartbeat.function = oz_pd_heartbeat_event; - pd->timeout.function = oz_pd_timeout_event; - - return pd; -} - -/* - * Context: softirq or process - */ -static void oz_pd_free(struct work_struct *work) -{ - struct list_head *e, *n; - struct oz_pd *pd; - - oz_pd_dbg(pd, ON, "Destroying PD\n"); - pd = container_of(work, struct oz_pd, workitem); - /*Disable timer tasklets*/ - tasklet_kill(&pd->heartbeat_tasklet); - tasklet_kill(&pd->timeout_tasklet); - - /* Free streams, queued tx frames and farewells. */ - - list_for_each_safe(e, n, &pd->stream_list) - oz_isoc_stream_free(list_entry(e, struct oz_isoc_stream, link)); - - list_for_each_safe(e, n, &pd->tx_queue) { - struct oz_tx_frame *f = list_entry(e, struct oz_tx_frame, link); - - if (f->skb != NULL) - kfree_skb(f->skb); - oz_retire_frame(pd, f); - } - - oz_elt_buf_term(&pd->elt_buff); - - list_for_each_safe(e, n, &pd->farewell_list) - kfree(list_entry(e, struct oz_farewell, link)); - - if (pd->net_dev) - dev_put(pd->net_dev); - kfree(pd); -} - -/* - * Context: softirq or Process - */ -void oz_pd_destroy(struct oz_pd *pd) -{ - if (hrtimer_active(&pd->timeout)) - hrtimer_cancel(&pd->timeout); - if (hrtimer_active(&pd->heartbeat)) - hrtimer_cancel(&pd->heartbeat); - - INIT_WORK(&pd->workitem, oz_pd_free); - if (!schedule_work(&pd->workitem)) - oz_pd_dbg(pd, ON, "failed to schedule workitem\n"); -} - -/* - * Context: softirq-serialized - */ -int oz_services_start(struct oz_pd *pd, u16 apps, int resume) -{ - int i, rc = 0; - - oz_pd_dbg(pd, ON, "%s: (0x%x) resume(%d)\n", __func__, apps, resume); - for (i = 0; i < OZ_NB_APPS; i++) { - if (g_app_if[i].start && (apps & (1 << i))) { - if (g_app_if[i].start(pd, resume)) { - rc = -1; - oz_pd_dbg(pd, ON, - "Unable to start service %d\n", i); - break; - } - spin_lock_bh(&g_polling_lock); - pd->total_apps |= (1 << i); - if (resume) - pd->paused_apps &= ~(1 << i); - spin_unlock_bh(&g_polling_lock); - } - } - return rc; -} - -/* - * Context: softirq or process - */ -void oz_services_stop(struct oz_pd *pd, u16 apps, int pause) -{ - int i; - - oz_pd_dbg(pd, ON, "%s: (0x%x) pause(%d)\n", __func__, apps, pause); - for (i = 0; i < OZ_NB_APPS; i++) { - if (g_app_if[i].stop && (apps & (1 << i))) { - spin_lock_bh(&g_polling_lock); - if (pause) { - pd->paused_apps |= (1 << i); - } else { - pd->total_apps &= ~(1 << i); - pd->paused_apps &= ~(1 << i); - } - spin_unlock_bh(&g_polling_lock); - g_app_if[i].stop(pd, pause); - } - } -} - -/* - * Context: softirq - */ -void oz_pd_heartbeat(struct oz_pd *pd, u16 apps) -{ - int i, more = 0; - - for (i = 0; i < OZ_NB_APPS; i++) { - if (g_app_if[i].heartbeat && (apps & (1 << i))) { - if (g_app_if[i].heartbeat(pd)) - more = 1; - } - } - if ((!more) && (hrtimer_active(&pd->heartbeat))) - hrtimer_cancel(&pd->heartbeat); - if (pd->mode & OZ_F_ISOC_ANYTIME) { - int count = 8; - - while (count-- && (oz_send_isoc_frame(pd) >= 0)) - ; - } -} - -/* - * Context: softirq or process - */ -void oz_pd_stop(struct oz_pd *pd) -{ - u16 stop_apps; - - oz_dbg(ON, "oz_pd_stop() State = 0x%x\n", pd->state); - oz_pd_indicate_farewells(pd); - spin_lock_bh(&g_polling_lock); - stop_apps = pd->total_apps; - pd->total_apps = 0; - pd->paused_apps = 0; - spin_unlock_bh(&g_polling_lock); - oz_services_stop(pd, stop_apps, 0); - spin_lock_bh(&g_polling_lock); - oz_pd_set_state(pd, OZ_PD_S_STOPPED); - /* Remove from PD list.*/ - list_del(&pd->link); - spin_unlock_bh(&g_polling_lock); - oz_dbg(ON, "pd ref count = %d\n", atomic_read(&pd->ref_count)); - oz_pd_put(pd); -} - -/* - * Context: softirq - */ -int oz_pd_sleep(struct oz_pd *pd) -{ - int do_stop = 0; - u16 stop_apps; - - spin_lock_bh(&g_polling_lock); - if (pd->state & (OZ_PD_S_SLEEP | OZ_PD_S_STOPPED)) { - spin_unlock_bh(&g_polling_lock); - return 0; - } - if (pd->keep_alive && pd->session_id) - oz_pd_set_state(pd, OZ_PD_S_SLEEP); - else - do_stop = 1; - - stop_apps = pd->total_apps; - spin_unlock_bh(&g_polling_lock); - if (do_stop) { - oz_pd_stop(pd); - } else { - oz_services_stop(pd, stop_apps, 1); - oz_timer_add(pd, OZ_TIMER_STOP, pd->keep_alive); - } - return do_stop; -} - -/* - * Context: softirq - */ -static struct oz_tx_frame *oz_tx_frame_alloc(struct oz_pd *pd) -{ - struct oz_tx_frame *f; - - f = kmem_cache_alloc(oz_tx_frame_cache, GFP_ATOMIC); - if (f) { - f->total_size = sizeof(struct oz_hdr); - INIT_LIST_HEAD(&f->link); - INIT_LIST_HEAD(&f->elt_list); - } - return f; -} - -/* - * Context: softirq or process - */ -static void oz_tx_isoc_free(struct oz_pd *pd, struct oz_tx_frame *f) -{ - pd->nb_queued_isoc_frames--; - list_del_init(&f->link); - - kmem_cache_free(oz_tx_frame_cache, f); - - oz_dbg(TX_FRAMES, "Releasing ISOC Frame isoc_nb= %d\n", - pd->nb_queued_isoc_frames); -} - -/* - * Context: softirq or process - */ -static void oz_tx_frame_free(struct oz_pd *pd, struct oz_tx_frame *f) -{ - kmem_cache_free(oz_tx_frame_cache, f); -} - -/* - * Context: softirq-serialized - */ -static void oz_set_more_bit(struct sk_buff *skb) -{ - struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb); - - oz_hdr->control |= OZ_F_MORE_DATA; -} - -/* - * Context: softirq-serialized - */ -static void oz_set_last_pkt_nb(struct oz_pd *pd, struct sk_buff *skb) -{ - struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb); - - oz_hdr->last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK; -} - -/* - * Context: softirq - */ -int oz_prepare_frame(struct oz_pd *pd, int empty) -{ - struct oz_tx_frame *f; - - if ((pd->mode & OZ_MODE_MASK) != OZ_MODE_TRIGGERED) - return -1; - if (pd->nb_queued_frames >= OZ_MAX_QUEUED_FRAMES) - return -1; - if (!empty && !oz_are_elts_available(&pd->elt_buff)) - return -1; - f = oz_tx_frame_alloc(pd); - if (f == NULL) - return -1; - f->skb = NULL; - f->hdr.control = - (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT) | OZ_F_ACK_REQUESTED; - ++pd->last_tx_pkt_num; - put_unaligned(cpu_to_le32(pd->last_tx_pkt_num), &f->hdr.pkt_num); - if (empty == 0) { - oz_select_elts_for_tx(&pd->elt_buff, 0, &f->total_size, - pd->max_tx_size, &f->elt_list); - } - spin_lock(&pd->tx_frame_lock); - list_add_tail(&f->link, &pd->tx_queue); - pd->nb_queued_frames++; - spin_unlock(&pd->tx_frame_lock); - return 0; -} - -/* - * Context: softirq-serialized - */ -static struct sk_buff *oz_build_frame(struct oz_pd *pd, struct oz_tx_frame *f) -{ - struct sk_buff *skb; - struct net_device *dev = pd->net_dev; - struct oz_hdr *oz_hdr; - struct oz_elt *elt; - struct oz_elt_info *ei; - - /* Allocate skb with enough space for the lower layers as well - * as the space we need. - */ - skb = alloc_skb(f->total_size + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC); - if (skb == NULL) - return NULL; - /* Reserve the head room for lower layers. - */ - skb_reserve(skb, LL_RESERVED_SPACE(dev)); - skb_reset_network_header(skb); - skb->dev = dev; - skb->protocol = htons(OZ_ETHERTYPE); - if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr, - dev->dev_addr, skb->len) < 0) - goto fail; - /* Push the tail to the end of the area we are going to copy to. - */ - oz_hdr = (struct oz_hdr *)skb_put(skb, f->total_size); - f->hdr.last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK; - memcpy(oz_hdr, &f->hdr, sizeof(struct oz_hdr)); - /* Copy the elements into the frame body. - */ - elt = (struct oz_elt *)(oz_hdr+1); - list_for_each_entry(ei, &f->elt_list, link) { - memcpy(elt, ei->data, ei->length); - elt = oz_next_elt(elt); - } - return skb; -fail: - kfree_skb(skb); - return NULL; -} - -/* - * Context: softirq or process - */ -static void oz_retire_frame(struct oz_pd *pd, struct oz_tx_frame *f) -{ - struct oz_elt_info *ei, *n; - - list_for_each_entry_safe(ei, n, &f->elt_list, link) { - list_del_init(&ei->link); - if (ei->callback) - ei->callback(pd, ei->context); - spin_lock_bh(&pd->elt_buff.lock); - oz_elt_info_free(&pd->elt_buff, ei); - spin_unlock_bh(&pd->elt_buff.lock); - } - oz_tx_frame_free(pd, f); -} - -/* - * Context: softirq-serialized - */ -static int oz_send_next_queued_frame(struct oz_pd *pd, int more_data) -{ - struct sk_buff *skb; - struct oz_tx_frame *f; - struct list_head *e; - - spin_lock(&pd->tx_frame_lock); - e = pd->last_sent_frame->next; - if (e == &pd->tx_queue) { - spin_unlock(&pd->tx_frame_lock); - return -1; - } - f = list_entry(e, struct oz_tx_frame, link); - - if (f->skb != NULL) { - skb = f->skb; - oz_tx_isoc_free(pd, f); - spin_unlock(&pd->tx_frame_lock); - if (more_data) - oz_set_more_bit(skb); - oz_set_last_pkt_nb(pd, skb); - if ((int)atomic_read(&g_submitted_isoc) < - OZ_MAX_SUBMITTED_ISOC) { - if (dev_queue_xmit(skb) < 0) { - oz_dbg(TX_FRAMES, "Dropping ISOC Frame\n"); - return -1; - } - atomic_inc(&g_submitted_isoc); - oz_dbg(TX_FRAMES, "Sending ISOC Frame, nb_isoc= %d\n", - pd->nb_queued_isoc_frames); - return 0; - } - kfree_skb(skb); - oz_dbg(TX_FRAMES, "Dropping ISOC Frame>\n"); - return -1; - } - - pd->last_sent_frame = e; - skb = oz_build_frame(pd, f); - spin_unlock(&pd->tx_frame_lock); - if (!skb) - return -1; - if (more_data) - oz_set_more_bit(skb); - oz_dbg(TX_FRAMES, "TX frame PN=0x%x\n", f->hdr.pkt_num); - if (dev_queue_xmit(skb) < 0) - return -1; - - return 0; -} - -/* - * Context: softirq-serialized - */ -void oz_send_queued_frames(struct oz_pd *pd, int backlog) -{ - while (oz_prepare_frame(pd, 0) >= 0) - backlog++; - - switch (pd->mode & (OZ_F_ISOC_NO_ELTS | OZ_F_ISOC_ANYTIME)) { - - case OZ_F_ISOC_NO_ELTS: { - backlog += pd->nb_queued_isoc_frames; - if (backlog <= 0) - goto out; - if (backlog > OZ_MAX_SUBMITTED_ISOC) - backlog = OZ_MAX_SUBMITTED_ISOC; - break; - } - case OZ_NO_ELTS_ANYTIME: { - if ((backlog <= 0) && (pd->isoc_sent == 0)) - goto out; - break; - } - default: { - if (backlog <= 0) - goto out; - break; - } - } - while (backlog--) { - if (oz_send_next_queued_frame(pd, backlog) < 0) - break; - } - return; - -out: oz_prepare_frame(pd, 1); - oz_send_next_queued_frame(pd, 0); -} - -/* - * Context: softirq - */ -static int oz_send_isoc_frame(struct oz_pd *pd) -{ - struct sk_buff *skb; - struct net_device *dev = pd->net_dev; - struct oz_hdr *oz_hdr; - struct oz_elt *elt; - struct oz_elt_info *ei; - LIST_HEAD(list); - int total_size = sizeof(struct oz_hdr); - - oz_select_elts_for_tx(&pd->elt_buff, 1, &total_size, - pd->max_tx_size, &list); - if (list_empty(&list)) - return 0; - skb = alloc_skb(total_size + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC); - if (skb == NULL) { - oz_dbg(ON, "Cannot alloc skb\n"); - oz_elt_info_free_chain(&pd->elt_buff, &list); - return -1; - } - skb_reserve(skb, LL_RESERVED_SPACE(dev)); - skb_reset_network_header(skb); - skb->dev = dev; - skb->protocol = htons(OZ_ETHERTYPE); - if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr, - dev->dev_addr, skb->len) < 0) { - kfree_skb(skb); - return -1; - } - oz_hdr = (struct oz_hdr *)skb_put(skb, total_size); - oz_hdr->control = (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT) | OZ_F_ISOC; - oz_hdr->last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK; - elt = (struct oz_elt *)(oz_hdr+1); - - list_for_each_entry(ei, &list, link) { - memcpy(elt, ei->data, ei->length); - elt = oz_next_elt(elt); - } - dev_queue_xmit(skb); - oz_elt_info_free_chain(&pd->elt_buff, &list); - return 0; -} - -/* - * Context: softirq-serialized - */ -void oz_retire_tx_frames(struct oz_pd *pd, u8 lpn) -{ - struct oz_tx_frame *f, *tmp = NULL; - u8 diff; - u32 pkt_num; - - LIST_HEAD(list); - - spin_lock(&pd->tx_frame_lock); - list_for_each_entry(f, &pd->tx_queue, link) { - pkt_num = le32_to_cpu(get_unaligned(&f->hdr.pkt_num)); - diff = (lpn - (pkt_num & OZ_LAST_PN_MASK)) & OZ_LAST_PN_MASK; - if ((diff > OZ_LAST_PN_HALF_CYCLE) || (pkt_num == 0)) - break; - oz_dbg(TX_FRAMES, "Releasing pkt_num= %u, nb= %d\n", - pkt_num, pd->nb_queued_frames); - tmp = f; - pd->nb_queued_frames--; - } - if (tmp) - list_cut_position(&list, &pd->tx_queue, &tmp->link); - pd->last_sent_frame = &pd->tx_queue; - spin_unlock(&pd->tx_frame_lock); - - list_for_each_entry_safe(f, tmp, &list, link) - oz_retire_frame(pd, f); -} - -/* - * Precondition: stream_lock must be held. - * Context: softirq - */ -static struct oz_isoc_stream *pd_stream_find(struct oz_pd *pd, u8 ep_num) -{ - struct oz_isoc_stream *st; - - list_for_each_entry(st, &pd->stream_list, link) { - if (st->ep_num == ep_num) - return st; - } - return NULL; -} - -/* - * Context: softirq - */ -int oz_isoc_stream_create(struct oz_pd *pd, u8 ep_num) -{ - struct oz_isoc_stream *st; - - st = kzalloc(sizeof(struct oz_isoc_stream), GFP_ATOMIC); - if (!st) - return -ENOMEM; - st->ep_num = ep_num; - spin_lock_bh(&pd->stream_lock); - if (!pd_stream_find(pd, ep_num)) { - list_add(&st->link, &pd->stream_list); - st = NULL; - } - spin_unlock_bh(&pd->stream_lock); - kfree(st); - return 0; -} - -/* - * Context: softirq or process - */ -static void oz_isoc_stream_free(struct oz_isoc_stream *st) -{ - kfree_skb(st->skb); - kfree(st); -} - -/* - * Context: softirq - */ -int oz_isoc_stream_delete(struct oz_pd *pd, u8 ep_num) -{ - struct oz_isoc_stream *st; - - spin_lock_bh(&pd->stream_lock); - st = pd_stream_find(pd, ep_num); - if (st) - list_del(&st->link); - spin_unlock_bh(&pd->stream_lock); - if (st) - oz_isoc_stream_free(st); - return 0; -} - -/* - * Context: any - */ -static void oz_isoc_destructor(struct sk_buff *skb) -{ - atomic_dec(&g_submitted_isoc); -} - -/* - * Context: softirq - */ -int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, const u8 *data, int len) -{ - struct net_device *dev = pd->net_dev; - struct oz_isoc_stream *st; - u8 nb_units = 0; - struct sk_buff *skb = NULL; - struct oz_hdr *oz_hdr = NULL; - int size = 0; - - spin_lock_bh(&pd->stream_lock); - st = pd_stream_find(pd, ep_num); - if (st) { - skb = st->skb; - st->skb = NULL; - nb_units = st->nb_units; - st->nb_units = 0; - oz_hdr = st->oz_hdr; - size = st->size; - } - spin_unlock_bh(&pd->stream_lock); - if (!st) - return 0; - if (!skb) { - /* Allocate enough space for max size frame. */ - skb = alloc_skb(pd->max_tx_size + OZ_ALLOCATED_SPACE(dev), - GFP_ATOMIC); - if (skb == NULL) - return 0; - /* Reserve the head room for lower layers. */ - skb_reserve(skb, LL_RESERVED_SPACE(dev)); - skb_reset_network_header(skb); - skb->dev = dev; - skb->protocol = htons(OZ_ETHERTYPE); - /* For audio packet set priority to AC_VO */ - skb->priority = 0x7; - size = sizeof(struct oz_hdr) + sizeof(struct oz_isoc_large); - oz_hdr = (struct oz_hdr *)skb_put(skb, size); - } - memcpy(skb_put(skb, len), data, len); - size += len; - if (++nb_units < pd->ms_per_isoc) { - spin_lock_bh(&pd->stream_lock); - st->skb = skb; - st->nb_units = nb_units; - st->oz_hdr = oz_hdr; - st->size = size; - spin_unlock_bh(&pd->stream_lock); - } else { - struct oz_hdr oz; - struct oz_isoc_large iso; - - spin_lock_bh(&pd->stream_lock); - iso.frame_number = st->frame_num; - st->frame_num += nb_units; - spin_unlock_bh(&pd->stream_lock); - oz.control = - (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT) | OZ_F_ISOC; - oz.last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK; - oz.pkt_num = 0; - iso.endpoint = ep_num; - iso.format = OZ_DATA_F_ISOC_LARGE; - iso.ms_data = nb_units; - memcpy(oz_hdr, &oz, sizeof(oz)); - memcpy(oz_hdr+1, &iso, sizeof(iso)); - if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr, - dev->dev_addr, skb->len) < 0) - goto out; - - skb->destructor = oz_isoc_destructor; - /*Queue for Xmit if mode is not ANYTIME*/ - if (!(pd->mode & OZ_F_ISOC_ANYTIME)) { - struct oz_tx_frame *isoc_unit = NULL; - int nb = pd->nb_queued_isoc_frames; - - if (nb >= pd->isoc_latency) { - struct oz_tx_frame *f; - - oz_dbg(TX_FRAMES, "Dropping ISOC Unit nb= %d\n", - nb); - spin_lock(&pd->tx_frame_lock); - list_for_each_entry(f, &pd->tx_queue, link) { - if (f->skb != NULL) { - oz_tx_isoc_free(pd, f); - break; - } - } - spin_unlock(&pd->tx_frame_lock); - } - isoc_unit = oz_tx_frame_alloc(pd); - if (isoc_unit == NULL) - goto out; - isoc_unit->hdr = oz; - isoc_unit->skb = skb; - spin_lock_bh(&pd->tx_frame_lock); - list_add_tail(&isoc_unit->link, &pd->tx_queue); - pd->nb_queued_isoc_frames++; - spin_unlock_bh(&pd->tx_frame_lock); - oz_dbg(TX_FRAMES, - "Added ISOC Frame to Tx Queue isoc_nb= %d, nb= %d\n", - pd->nb_queued_isoc_frames, pd->nb_queued_frames); - return 0; - } - - /*In ANYTIME mode Xmit unit immediately*/ - if (atomic_read(&g_submitted_isoc) < OZ_MAX_SUBMITTED_ISOC) { - atomic_inc(&g_submitted_isoc); - if (dev_queue_xmit(skb) < 0) - return -1; - return 0; - } - -out: kfree_skb(skb); - return -1; - - } - return 0; -} - -/* - * Context: process - */ -void oz_apps_init(void) -{ - int i; - - for (i = 0; i < OZ_NB_APPS; i++) { - if (g_app_if[i].init) - g_app_if[i].init(); - } -} - -/* - * Context: process - */ -void oz_apps_term(void) -{ - int i; - - /* Terminate all the apps. */ - for (i = 0; i < OZ_NB_APPS; i++) { - if (g_app_if[i].term) - g_app_if[i].term(); - } -} - -/* - * Context: softirq-serialized - */ -void oz_handle_app_elt(struct oz_pd *pd, u8 app_id, struct oz_elt *elt) -{ - if (app_id < OZ_NB_APPS && g_app_if[app_id].rx) - g_app_if[app_id].rx(pd, elt); -} - -/* - * Context: softirq or process - */ -void oz_pd_indicate_farewells(struct oz_pd *pd) -{ - struct oz_farewell *f; - const struct oz_app_if *ai = &g_app_if[OZ_APPID_USB]; - - while (1) { - spin_lock_bh(&g_polling_lock); - if (list_empty(&pd->farewell_list)) { - spin_unlock_bh(&g_polling_lock); - break; - } - f = list_first_entry(&pd->farewell_list, - struct oz_farewell, link); - list_del(&f->link); - spin_unlock_bh(&g_polling_lock); - if (ai->farewell) - ai->farewell(pd, f->ep_num, f->report, f->len); - kfree(f); - } -} diff --git a/drivers/staging/ozwpan/ozpd.h b/drivers/staging/ozwpan/ozpd.h deleted file mode 100644 index 212fab0d807a..000000000000 --- a/drivers/staging/ozwpan/ozpd.h +++ /dev/null @@ -1,134 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * ----------------------------------------------------------------------------- - */ -#ifndef _OZPD_H_ -#define _OZPD_H_ - -#include <linux/interrupt.h> -#include "ozeltbuf.h" - -/* PD state - */ -#define OZ_PD_S_IDLE 0x1 -#define OZ_PD_S_CONNECTED 0x2 -#define OZ_PD_S_SLEEP 0x4 -#define OZ_PD_S_STOPPED 0x8 - -/* Timer event types. - */ -#define OZ_TIMER_TOUT 1 -#define OZ_TIMER_HEARTBEAT 2 -#define OZ_TIMER_STOP 3 - -/* - *External spinlock variable - */ -extern spinlock_t g_polling_lock; - -/* Data structure that hold information on a frame for transmisson. This is - * built when the frame is first transmitted and is used to rebuild the frame - * if a re-transmission is required. - */ -struct oz_tx_frame { - struct list_head link; - struct list_head elt_list; - struct oz_hdr hdr; - struct sk_buff *skb; - int total_size; -}; - -struct oz_isoc_stream { - struct list_head link; - u8 ep_num; - u8 frame_num; - u8 nb_units; - int size; - struct sk_buff *skb; - struct oz_hdr *oz_hdr; -}; - -struct oz_farewell { - struct list_head link; - u8 ep_num; - u8 index; - u8 len; - u8 report[0]; -}; - -/* Data structure that holds information on a specific peripheral device (PD). - */ -struct oz_pd { - struct list_head link; - atomic_t ref_count; - u8 mac_addr[ETH_ALEN]; - unsigned state; - unsigned state_flags; - unsigned send_flags; - u16 total_apps; - u16 paused_apps; - u8 session_id; - u8 param_rsp_status; - u8 pd_info; - u8 isoc_sent; - u32 last_rx_pkt_num; - u32 last_tx_pkt_num; - struct timespec last_rx_timestamp; - u32 trigger_pkt_num; - unsigned long pulse_time; - unsigned long pulse_period; - unsigned long presleep; - unsigned long keep_alive; - struct oz_elt_buf elt_buff; - void *app_ctx[OZ_NB_APPS]; - spinlock_t app_lock[OZ_NB_APPS]; - int max_tx_size; - u8 mode; - u8 ms_per_isoc; - unsigned isoc_latency; - unsigned max_stream_buffering; - int nb_queued_frames; - int nb_queued_isoc_frames; - spinlock_t tx_frame_lock; - struct list_head *last_sent_frame; - struct list_head tx_queue; - struct list_head farewell_list; - spinlock_t stream_lock; - struct list_head stream_list; - struct net_device *net_dev; - struct hrtimer heartbeat; - struct hrtimer timeout; - u8 timeout_type; - struct tasklet_struct heartbeat_tasklet; - struct tasklet_struct timeout_tasklet; - struct work_struct workitem; -}; - -#define OZ_MAX_QUEUED_FRAMES 4 - -struct oz_pd *oz_pd_alloc(const u8 *mac_addr); -void oz_pd_destroy(struct oz_pd *pd); -void oz_pd_get(struct oz_pd *pd); -void oz_pd_put(struct oz_pd *pd); -void oz_pd_set_state(struct oz_pd *pd, unsigned state); -void oz_pd_indicate_farewells(struct oz_pd *pd); -int oz_pd_sleep(struct oz_pd *pd); -void oz_pd_stop(struct oz_pd *pd); -void oz_pd_heartbeat(struct oz_pd *pd, u16 apps); -int oz_services_start(struct oz_pd *pd, u16 apps, int resume); -void oz_services_stop(struct oz_pd *pd, u16 apps, int pause); -int oz_prepare_frame(struct oz_pd *pd, int empty); -void oz_send_queued_frames(struct oz_pd *pd, int backlog); -void oz_retire_tx_frames(struct oz_pd *pd, u8 lpn); -int oz_isoc_stream_create(struct oz_pd *pd, u8 ep_num); -int oz_isoc_stream_delete(struct oz_pd *pd, u8 ep_num); -int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, const u8 *data, int len); -void oz_handle_app_elt(struct oz_pd *pd, u8 app_id, struct oz_elt *elt); -void oz_apps_init(void); -void oz_apps_term(void); - -extern struct kmem_cache *oz_elt_info_cache; -extern struct kmem_cache *oz_tx_frame_cache; - -#endif /* Sentry */ diff --git a/drivers/staging/ozwpan/ozproto.c b/drivers/staging/ozwpan/ozproto.c deleted file mode 100644 index 1ba24a2aef83..000000000000 --- a/drivers/staging/ozwpan/ozproto.c +++ /dev/null @@ -1,813 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * ----------------------------------------------------------------------------- - */ - -#include <linux/module.h> -#include <linux/timer.h> -#include <linux/sched.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/errno.h> -#include <linux/ieee80211.h> -#include <linux/slab.h> -#include "ozdbg.h" -#include "ozprotocol.h" -#include "ozeltbuf.h" -#include "ozpd.h" -#include "ozproto.h" -#include "ozusbsvc.h" - -#include "ozappif.h" -#include <asm/unaligned.h> -#include <linux/uaccess.h> -#include <net/psnap.h> - -#define OZ_CF_CONN_SUCCESS 1 -#define OZ_CF_CONN_FAILURE 2 - -#define OZ_DO_STOP 1 -#define OZ_DO_SLEEP 2 - -struct oz_binding { - struct packet_type ptype; - char name[OZ_MAX_BINDING_LEN]; - struct list_head link; -}; - -/* - * External variable - */ - -DEFINE_SPINLOCK(g_polling_lock); -/* - * Static external variables. - */ -static LIST_HEAD(g_pd_list); -static LIST_HEAD(g_binding); -static DEFINE_SPINLOCK(g_binding_lock); -static struct sk_buff_head g_rx_queue; -static u8 g_session_id; -static u16 g_apps = 0x1; -static int g_processing_rx; - -struct kmem_cache *oz_elt_info_cache; -struct kmem_cache *oz_tx_frame_cache; - -/* - * Context: softirq-serialized - */ -static u8 oz_get_new_session_id(u8 exclude) -{ - if (++g_session_id == 0) - g_session_id = 1; - if (g_session_id == exclude) { - if (++g_session_id == 0) - g_session_id = 1; - } - return g_session_id; -} - -/* - * Context: softirq-serialized - */ -static void oz_send_conn_rsp(struct oz_pd *pd, u8 status) -{ - struct sk_buff *skb; - struct net_device *dev = pd->net_dev; - struct oz_hdr *oz_hdr; - struct oz_elt *elt; - struct oz_elt_connect_rsp *body; - - int sz = sizeof(struct oz_hdr) + sizeof(struct oz_elt) + - sizeof(struct oz_elt_connect_rsp); - skb = alloc_skb(sz + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC); - if (skb == NULL) - return; - skb_reserve(skb, LL_RESERVED_SPACE(dev)); - skb_reset_network_header(skb); - oz_hdr = (struct oz_hdr *)skb_put(skb, sz); - elt = (struct oz_elt *)(oz_hdr+1); - body = (struct oz_elt_connect_rsp *)(elt+1); - skb->dev = dev; - skb->protocol = htons(OZ_ETHERTYPE); - /* Fill in device header */ - if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr, - dev->dev_addr, skb->len) < 0) { - kfree_skb(skb); - return; - } - oz_hdr->control = OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT; - oz_hdr->last_pkt_num = 0; - put_unaligned(0, &oz_hdr->pkt_num); - elt->type = OZ_ELT_CONNECT_RSP; - elt->length = sizeof(struct oz_elt_connect_rsp); - memset(body, 0, sizeof(struct oz_elt_connect_rsp)); - body->status = status; - if (status == 0) { - body->mode = pd->mode; - body->session_id = pd->session_id; - put_unaligned(cpu_to_le16(pd->total_apps), &body->apps); - } - oz_dbg(ON, "TX: OZ_ELT_CONNECT_RSP %d", status); - dev_queue_xmit(skb); -} - -/* - * Context: softirq-serialized - */ -static void pd_set_keepalive(struct oz_pd *pd, u8 kalive) -{ - unsigned long keep_alive = kalive & OZ_KALIVE_VALUE_MASK; - - switch (kalive & OZ_KALIVE_TYPE_MASK) { - case OZ_KALIVE_SPECIAL: - pd->keep_alive = keep_alive * 1000*60*60*24*20; - break; - case OZ_KALIVE_SECS: - pd->keep_alive = keep_alive*1000; - break; - case OZ_KALIVE_MINS: - pd->keep_alive = keep_alive*1000*60; - break; - case OZ_KALIVE_HOURS: - pd->keep_alive = keep_alive*1000*60*60; - break; - default: - pd->keep_alive = 0; - } - oz_dbg(ON, "Keepalive = %lu mSec\n", pd->keep_alive); -} - -/* - * Context: softirq-serialized - */ -static void pd_set_presleep(struct oz_pd *pd, u8 presleep, u8 start_timer) -{ - if (presleep) - pd->presleep = presleep*100; - else - pd->presleep = OZ_PRESLEEP_TOUT; - if (start_timer) { - spin_unlock(&g_polling_lock); - oz_timer_add(pd, OZ_TIMER_TOUT, pd->presleep); - spin_lock(&g_polling_lock); - } - oz_dbg(ON, "Presleep time = %lu mSec\n", pd->presleep); -} - -/* - * Context: softirq-serialized - */ -static struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt, - const u8 *pd_addr, struct net_device *net_dev) -{ - struct oz_pd *pd; - struct oz_elt_connect_req *body = - (struct oz_elt_connect_req *)(elt+1); - u8 rsp_status = OZ_STATUS_SUCCESS; - u8 stop_needed = 0; - u16 new_apps = g_apps; - struct net_device *old_net_dev = NULL; - struct oz_pd *free_pd = NULL; - - if (cur_pd) { - pd = cur_pd; - spin_lock_bh(&g_polling_lock); - } else { - struct oz_pd *pd2 = NULL; - struct list_head *e; - - pd = oz_pd_alloc(pd_addr); - if (pd == NULL) - return NULL; - getnstimeofday(&pd->last_rx_timestamp); - spin_lock_bh(&g_polling_lock); - list_for_each(e, &g_pd_list) { - pd2 = list_entry(e, struct oz_pd, link); - if (ether_addr_equal(pd2->mac_addr, pd_addr)) { - free_pd = pd; - pd = pd2; - break; - } - } - if (pd != pd2) - list_add_tail(&pd->link, &g_pd_list); - } - if (pd == NULL) { - spin_unlock_bh(&g_polling_lock); - return NULL; - } - if (pd->net_dev != net_dev) { - old_net_dev = pd->net_dev; - dev_hold(net_dev); - pd->net_dev = net_dev; - } - oz_dbg(ON, "Host vendor: %d\n", body->host_vendor); - pd->max_tx_size = OZ_MAX_TX_SIZE; - pd->mode = body->mode; - pd->pd_info = body->pd_info; - if (pd->mode & OZ_F_ISOC_NO_ELTS) { - pd->ms_per_isoc = body->ms_per_isoc; - if (!pd->ms_per_isoc) - pd->ms_per_isoc = 4; - - switch (body->ms_isoc_latency & OZ_LATENCY_MASK) { - case OZ_ONE_MS_LATENCY: - pd->isoc_latency = (body->ms_isoc_latency & - ~OZ_LATENCY_MASK) / pd->ms_per_isoc; - break; - case OZ_TEN_MS_LATENCY: - pd->isoc_latency = ((body->ms_isoc_latency & - ~OZ_LATENCY_MASK) * 10) / pd->ms_per_isoc; - break; - default: - pd->isoc_latency = OZ_MAX_TX_QUEUE_ISOC; - } - } - if (body->max_len_div16) - pd->max_tx_size = ((u16)body->max_len_div16)<<4; - oz_dbg(ON, "Max frame:%u Ms per isoc:%u\n", - pd->max_tx_size, pd->ms_per_isoc); - pd->max_stream_buffering = 3*1024; - pd->pulse_period = OZ_QUANTUM; - pd_set_presleep(pd, body->presleep, 0); - pd_set_keepalive(pd, body->keep_alive); - - new_apps &= le16_to_cpu(get_unaligned(&body->apps)); - if ((new_apps & 0x1) && (body->session_id)) { - if (pd->session_id) { - if (pd->session_id != body->session_id) { - rsp_status = OZ_STATUS_SESSION_MISMATCH; - goto done; - } - } else { - new_apps &= ~0x1; /* Resume not permitted */ - pd->session_id = - oz_get_new_session_id(body->session_id); - } - } else { - if (pd->session_id && !body->session_id) { - rsp_status = OZ_STATUS_SESSION_TEARDOWN; - stop_needed = 1; - } else { - new_apps &= ~0x1; /* Resume not permitted */ - pd->session_id = - oz_get_new_session_id(body->session_id); - } - } -done: - if (rsp_status == OZ_STATUS_SUCCESS) { - u16 start_apps = new_apps & ~pd->total_apps & ~0x1; - u16 stop_apps = pd->total_apps & ~new_apps & ~0x1; - u16 resume_apps = new_apps & pd->paused_apps & ~0x1; - - spin_unlock_bh(&g_polling_lock); - oz_pd_set_state(pd, OZ_PD_S_CONNECTED); - oz_dbg(ON, "new_apps=0x%x total_apps=0x%x paused_apps=0x%x\n", - new_apps, pd->total_apps, pd->paused_apps); - if (start_apps) { - if (oz_services_start(pd, start_apps, 0)) - rsp_status = OZ_STATUS_TOO_MANY_PDS; - } - if (resume_apps) - if (oz_services_start(pd, resume_apps, 1)) - rsp_status = OZ_STATUS_TOO_MANY_PDS; - if (stop_apps) - oz_services_stop(pd, stop_apps, 0); - oz_pd_request_heartbeat(pd); - } else { - spin_unlock_bh(&g_polling_lock); - } - oz_send_conn_rsp(pd, rsp_status); - if (rsp_status != OZ_STATUS_SUCCESS) { - if (stop_needed) - oz_pd_stop(pd); - oz_pd_put(pd); - pd = NULL; - } - if (old_net_dev) - dev_put(old_net_dev); - if (free_pd) - oz_pd_destroy(free_pd); - return pd; -} - -/* - * Context: softirq-serialized - */ -static void oz_add_farewell(struct oz_pd *pd, u8 ep_num, u8 index, - const u8 *report, u8 len) -{ - struct oz_farewell *f; - struct oz_farewell *f2; - int found = 0; - - f = kmalloc(sizeof(struct oz_farewell) + len, GFP_ATOMIC); - if (!f) - return; - f->ep_num = ep_num; - f->index = index; - f->len = len; - memcpy(f->report, report, len); - oz_dbg(ON, "RX: Adding farewell report\n"); - spin_lock(&g_polling_lock); - list_for_each_entry(f2, &pd->farewell_list, link) { - if ((f2->ep_num == ep_num) && (f2->index == index)) { - found = 1; - list_del(&f2->link); - break; - } - } - list_add_tail(&f->link, &pd->farewell_list); - spin_unlock(&g_polling_lock); - if (found) - kfree(f2); -} - -/* - * Context: softirq-serialized - */ -static void oz_rx_frame(struct sk_buff *skb) -{ - u8 *mac_hdr; - u8 *src_addr; - struct oz_elt *elt; - int length; - struct oz_pd *pd = NULL; - struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb); - struct timespec current_time; - int dup = 0; - u32 pkt_num; - - oz_dbg(RX_FRAMES, "RX frame PN=0x%x LPN=0x%x control=0x%x\n", - oz_hdr->pkt_num, oz_hdr->last_pkt_num, oz_hdr->control); - mac_hdr = skb_mac_header(skb); - src_addr = &mac_hdr[ETH_ALEN]; - length = skb->len; - - /* Check the version field */ - if (oz_get_prot_ver(oz_hdr->control) != OZ_PROTOCOL_VERSION) { - oz_dbg(ON, "Incorrect protocol version: %d\n", - oz_get_prot_ver(oz_hdr->control)); - goto done; - } - - pkt_num = le32_to_cpu(get_unaligned(&oz_hdr->pkt_num)); - - pd = oz_pd_find(src_addr); - if (pd) { - if (!(pd->state & OZ_PD_S_CONNECTED)) - oz_pd_set_state(pd, OZ_PD_S_CONNECTED); - getnstimeofday(¤t_time); - if ((current_time.tv_sec != pd->last_rx_timestamp.tv_sec) || - (pd->presleep < MSEC_PER_SEC)) { - oz_timer_add(pd, OZ_TIMER_TOUT, pd->presleep); - pd->last_rx_timestamp = current_time; - } - if (pkt_num != pd->last_rx_pkt_num) { - pd->last_rx_pkt_num = pkt_num; - } else { - dup = 1; - oz_dbg(ON, "Duplicate frame\n"); - } - } - - if (pd && !dup && ((pd->mode & OZ_MODE_MASK) == OZ_MODE_TRIGGERED)) { - oz_dbg(RX_FRAMES, "Received TRIGGER Frame\n"); - pd->last_sent_frame = &pd->tx_queue; - if (oz_hdr->control & OZ_F_ACK) { - /* Retire completed frames */ - oz_retire_tx_frames(pd, oz_hdr->last_pkt_num); - } - if ((oz_hdr->control & OZ_F_ACK_REQUESTED) && - (pd->state == OZ_PD_S_CONNECTED)) { - int backlog = pd->nb_queued_frames; - - pd->trigger_pkt_num = pkt_num; - /* Send queued frames */ - oz_send_queued_frames(pd, backlog); - } - } - - length -= sizeof(struct oz_hdr); - elt = (struct oz_elt *)((u8 *)oz_hdr + sizeof(struct oz_hdr)); - - while (length >= sizeof(struct oz_elt)) { - length -= sizeof(struct oz_elt) + elt->length; - if (length < 0) - break; - switch (elt->type) { - case OZ_ELT_CONNECT_REQ: - oz_dbg(ON, "RX: OZ_ELT_CONNECT_REQ\n"); - pd = oz_connect_req(pd, elt, src_addr, skb->dev); - break; - case OZ_ELT_DISCONNECT: - oz_dbg(ON, "RX: OZ_ELT_DISCONNECT\n"); - if (pd) - oz_pd_sleep(pd); - break; - case OZ_ELT_UPDATE_PARAM_REQ: { - struct oz_elt_update_param *body = - (struct oz_elt_update_param *)(elt + 1); - oz_dbg(ON, "RX: OZ_ELT_UPDATE_PARAM_REQ\n"); - if (pd && (pd->state & OZ_PD_S_CONNECTED)) { - spin_lock(&g_polling_lock); - pd_set_keepalive(pd, body->keepalive); - pd_set_presleep(pd, body->presleep, 1); - spin_unlock(&g_polling_lock); - } - } - break; - case OZ_ELT_FAREWELL_REQ: { - struct oz_elt_farewell *body = - (struct oz_elt_farewell *)(elt + 1); - oz_dbg(ON, "RX: OZ_ELT_FAREWELL_REQ\n"); - oz_add_farewell(pd, body->ep_num, - body->index, body->report, - elt->length + 1 - sizeof(*body)); - } - break; - case OZ_ELT_APP_DATA: - if (pd && (pd->state & OZ_PD_S_CONNECTED)) { - struct oz_app_hdr *app_hdr = - (struct oz_app_hdr *)(elt+1); - if (dup) - break; - oz_handle_app_elt(pd, app_hdr->app_id, elt); - } - break; - default: - oz_dbg(ON, "RX: Unknown elt %02x\n", elt->type); - } - elt = oz_next_elt(elt); - } -done: - if (pd) - oz_pd_put(pd); - consume_skb(skb); -} - -/* - * Context: process - */ -void oz_protocol_term(void) -{ - struct oz_binding *b, *t; - - /* Walk the list of bindings and remove each one. - */ - spin_lock_bh(&g_binding_lock); - list_for_each_entry_safe(b, t, &g_binding, link) { - list_del(&b->link); - spin_unlock_bh(&g_binding_lock); - dev_remove_pack(&b->ptype); - if (b->ptype.dev) - dev_put(b->ptype.dev); - kfree(b); - spin_lock_bh(&g_binding_lock); - } - spin_unlock_bh(&g_binding_lock); - /* Walk the list of PDs and stop each one. This causes the PD to be - * removed from the list so we can just pull each one from the head - * of the list. - */ - spin_lock_bh(&g_polling_lock); - while (!list_empty(&g_pd_list)) { - struct oz_pd *pd = - list_first_entry(&g_pd_list, struct oz_pd, link); - oz_pd_get(pd); - spin_unlock_bh(&g_polling_lock); - oz_pd_stop(pd); - oz_pd_put(pd); - spin_lock_bh(&g_polling_lock); - } - spin_unlock_bh(&g_polling_lock); - oz_dbg(ON, "Protocol stopped\n"); - - kmem_cache_destroy(oz_tx_frame_cache); - kmem_cache_destroy(oz_elt_info_cache); -} - -/* - * Context: softirq - */ -void oz_pd_heartbeat_handler(unsigned long data) -{ - struct oz_pd *pd = (struct oz_pd *)data; - u16 apps = 0; - - spin_lock_bh(&g_polling_lock); - if (pd->state & OZ_PD_S_CONNECTED) - apps = pd->total_apps; - spin_unlock_bh(&g_polling_lock); - if (apps) - oz_pd_heartbeat(pd, apps); - oz_pd_put(pd); -} - -/* - * Context: softirq - */ -void oz_pd_timeout_handler(unsigned long data) -{ - int type; - struct oz_pd *pd = (struct oz_pd *)data; - - spin_lock_bh(&g_polling_lock); - type = pd->timeout_type; - spin_unlock_bh(&g_polling_lock); - switch (type) { - case OZ_TIMER_TOUT: - oz_pd_sleep(pd); - break; - case OZ_TIMER_STOP: - oz_pd_stop(pd); - break; - } - oz_pd_put(pd); -} - -/* - * Context: Interrupt - */ -enum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer) -{ - struct oz_pd *pd; - - pd = container_of(timer, struct oz_pd, heartbeat); - hrtimer_forward_now(timer, ktime_set(pd->pulse_period / - MSEC_PER_SEC, (pd->pulse_period % MSEC_PER_SEC) * NSEC_PER_MSEC)); - oz_pd_get(pd); - tasklet_schedule(&pd->heartbeat_tasklet); - return HRTIMER_RESTART; -} - -/* - * Context: Interrupt - */ -enum hrtimer_restart oz_pd_timeout_event(struct hrtimer *timer) -{ - struct oz_pd *pd; - - pd = container_of(timer, struct oz_pd, timeout); - oz_pd_get(pd); - tasklet_schedule(&pd->timeout_tasklet); - return HRTIMER_NORESTART; -} - -/* - * Context: softirq or process - */ -void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time) -{ - spin_lock_bh(&g_polling_lock); - switch (type) { - case OZ_TIMER_TOUT: - case OZ_TIMER_STOP: - if (hrtimer_active(&pd->timeout)) { - hrtimer_set_expires(&pd->timeout, ktime_set(due_time / - MSEC_PER_SEC, (due_time % MSEC_PER_SEC) * - NSEC_PER_MSEC)); - hrtimer_start_expires(&pd->timeout, HRTIMER_MODE_REL); - } else { - hrtimer_start(&pd->timeout, ktime_set(due_time / - MSEC_PER_SEC, (due_time % MSEC_PER_SEC) * - NSEC_PER_MSEC), HRTIMER_MODE_REL); - } - pd->timeout_type = type; - break; - case OZ_TIMER_HEARTBEAT: - if (!hrtimer_active(&pd->heartbeat)) - hrtimer_start(&pd->heartbeat, ktime_set(due_time / - MSEC_PER_SEC, (due_time % MSEC_PER_SEC) * - NSEC_PER_MSEC), HRTIMER_MODE_REL); - break; - } - spin_unlock_bh(&g_polling_lock); -} - -/* - * Context: softirq or process - */ -void oz_pd_request_heartbeat(struct oz_pd *pd) -{ - oz_timer_add(pd, OZ_TIMER_HEARTBEAT, pd->pulse_period > 0 ? - pd->pulse_period : OZ_QUANTUM); -} - -/* - * Context: softirq or process - */ -struct oz_pd *oz_pd_find(const u8 *mac_addr) -{ - struct oz_pd *pd; - - spin_lock_bh(&g_polling_lock); - list_for_each_entry(pd, &g_pd_list, link) { - if (ether_addr_equal(pd->mac_addr, mac_addr)) { - oz_pd_get(pd); - spin_unlock_bh(&g_polling_lock); - return pd; - } - } - spin_unlock_bh(&g_polling_lock); - return NULL; -} - -/* - * Context: process - */ -void oz_app_enable(int app_id, int enable) -{ - if (app_id < OZ_NB_APPS) { - spin_lock_bh(&g_polling_lock); - if (enable) - g_apps |= (1<<app_id); - else - g_apps &= ~(1<<app_id); - spin_unlock_bh(&g_polling_lock); - } -} - -/* - * Context: softirq - */ -static int oz_pkt_recv(struct sk_buff *skb, struct net_device *dev, - struct packet_type *pt, struct net_device *orig_dev) -{ - skb = skb_share_check(skb, GFP_ATOMIC); - if (skb == NULL) - return 0; - spin_lock_bh(&g_rx_queue.lock); - if (g_processing_rx) { - /* We already hold the lock so use __ variant. - */ - __skb_queue_head(&g_rx_queue, skb); - spin_unlock_bh(&g_rx_queue.lock); - } else { - g_processing_rx = 1; - do { - - spin_unlock_bh(&g_rx_queue.lock); - oz_rx_frame(skb); - spin_lock_bh(&g_rx_queue.lock); - if (skb_queue_empty(&g_rx_queue)) { - g_processing_rx = 0; - spin_unlock_bh(&g_rx_queue.lock); - break; - } - /* We already hold the lock so use __ variant. - */ - skb = __skb_dequeue(&g_rx_queue); - } while (1); - } - return 0; -} - -/* - * Context: process - */ -void oz_binding_add(const char *net_dev) -{ - struct oz_binding *binding; - - binding = kzalloc(sizeof(struct oz_binding), GFP_KERNEL); - if (!binding) - return; - - binding->ptype.type = htons(OZ_ETHERTYPE); - binding->ptype.func = oz_pkt_recv; - if (net_dev && *net_dev) { - memcpy(binding->name, net_dev, OZ_MAX_BINDING_LEN); - oz_dbg(ON, "Adding binding: %s\n", net_dev); - binding->ptype.dev = dev_get_by_name(&init_net, net_dev); - if (binding->ptype.dev == NULL) { - oz_dbg(ON, "Netdev %s not found\n", net_dev); - kfree(binding); - return; - } - } - dev_add_pack(&binding->ptype); - spin_lock_bh(&g_binding_lock); - list_add_tail(&binding->link, &g_binding); - spin_unlock_bh(&g_binding_lock); -} - -/* - * Context: process - */ -static void pd_stop_all_for_device(struct net_device *net_dev) -{ - LIST_HEAD(h); - struct oz_pd *pd; - struct oz_pd *n; - - spin_lock_bh(&g_polling_lock); - list_for_each_entry_safe(pd, n, &g_pd_list, link) { - if (pd->net_dev == net_dev) { - list_move(&pd->link, &h); - oz_pd_get(pd); - } - } - spin_unlock_bh(&g_polling_lock); - while (!list_empty(&h)) { - pd = list_first_entry(&h, struct oz_pd, link); - oz_pd_stop(pd); - oz_pd_put(pd); - } -} - -/* - * Context: process - */ -void oz_binding_remove(const char *net_dev) -{ - struct oz_binding *binding; - int found = 0; - - oz_dbg(ON, "Removing binding: %s\n", net_dev); - spin_lock_bh(&g_binding_lock); - list_for_each_entry(binding, &g_binding, link) { - if (strncmp(binding->name, net_dev, OZ_MAX_BINDING_LEN) == 0) { - oz_dbg(ON, "Binding '%s' found\n", net_dev); - found = 1; - break; - } - } - spin_unlock_bh(&g_binding_lock); - if (found) { - dev_remove_pack(&binding->ptype); - if (binding->ptype.dev) { - dev_put(binding->ptype.dev); - pd_stop_all_for_device(binding->ptype.dev); - } - list_del(&binding->link); - kfree(binding); - } -} - -/* - * Context: process - */ -static char *oz_get_next_device_name(char *s, char *dname, int max_size) -{ - while (*s == ',') - s++; - while (*s && (*s != ',') && max_size > 1) { - *dname++ = *s++; - max_size--; - } - *dname = 0; - return s; -} - -/* - * Context: process - */ -int oz_protocol_init(char *devs) -{ - oz_elt_info_cache = KMEM_CACHE(oz_elt_info, 0); - if (!oz_elt_info_cache) - return -ENOMEM; - - oz_tx_frame_cache = KMEM_CACHE(oz_tx_frame, 0); - if (!oz_tx_frame_cache) { - kmem_cache_destroy(oz_elt_info_cache); - return -ENOMEM; - } - - skb_queue_head_init(&g_rx_queue); - if (devs[0] == '*') { - oz_binding_add(NULL); - } else { - char d[32]; - - while (*devs) { - devs = oz_get_next_device_name(devs, d, sizeof(d)); - if (d[0]) - oz_binding_add(d); - } - } - return 0; -} - -/* - * Context: process - */ -int oz_get_pd_list(struct oz_mac_addr *addr, int max_count) -{ - struct oz_pd *pd; - int count = 0; - - spin_lock_bh(&g_polling_lock); - list_for_each_entry(pd, &g_pd_list, link) { - if (count >= max_count) - break; - ether_addr_copy((u8 *)&addr[count++], pd->mac_addr); - } - spin_unlock_bh(&g_polling_lock); - return count; -} - diff --git a/drivers/staging/ozwpan/ozproto.h b/drivers/staging/ozwpan/ozproto.h deleted file mode 100644 index 30c2db91c000..000000000000 --- a/drivers/staging/ozwpan/ozproto.h +++ /dev/null @@ -1,62 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * ----------------------------------------------------------------------------- - */ -#ifndef _OZPROTO_H -#define _OZPROTO_H - -#include <asm/byteorder.h> -#include "ozdbg.h" -#include "ozappif.h" - -#define OZ_ALLOCATED_SPACE(__x) (LL_RESERVED_SPACE(__x)+(__x)->needed_tailroom) - -/* Quantum in MS */ -#define OZ_QUANTUM 8 -/* Default timeouts. - */ -#define OZ_PRESLEEP_TOUT 11 - -/* Maximun sizes of tx frames. */ -#define OZ_MAX_TX_SIZE 760 - -/* Maximum number of uncompleted isoc frames that can be pending in network. */ -#define OZ_MAX_SUBMITTED_ISOC 16 - -/* Maximum number of uncompleted isoc frames that can be pending in Tx Queue. */ -#define OZ_MAX_TX_QUEUE_ISOC 32 - -/* Application handler functions. - */ -struct oz_app_if { - int (*init)(void); - void (*term)(void); - int (*start)(struct oz_pd *pd, int resume); - void (*stop)(struct oz_pd *pd, int pause); - void (*rx)(struct oz_pd *pd, struct oz_elt *elt); - int (*heartbeat)(struct oz_pd *pd); - void (*farewell)(struct oz_pd *pd, u8 ep_num, u8 *data, u8 len); -}; - -int oz_protocol_init(char *devs); -void oz_protocol_term(void); -int oz_get_pd_list(struct oz_mac_addr *addr, int max_count); -void oz_app_enable(int app_id, int enable); -struct oz_pd *oz_pd_find(const u8 *mac_addr); -void oz_binding_add(const char *net_dev); -void oz_binding_remove(const char *net_dev); -void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time); -void oz_timer_delete(struct oz_pd *pd, int type); -void oz_pd_request_heartbeat(struct oz_pd *pd); -void oz_pd_heartbeat_handler(unsigned long data); -void oz_pd_timeout_handler(unsigned long data); -enum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer); -enum hrtimer_restart oz_pd_timeout_event(struct hrtimer *timer); -int oz_get_pd_status_list(char *pd_list, int max_count); -int oz_get_binding_list(char *buf, int max_if); - -extern struct kmem_cache *oz_elt_info_cache; -extern struct kmem_cache *oz_tx_frame_cache; - -#endif /* _OZPROTO_H */ diff --git a/drivers/staging/ozwpan/ozprotocol.h b/drivers/staging/ozwpan/ozprotocol.h deleted file mode 100644 index 4642072596da..000000000000 --- a/drivers/staging/ozwpan/ozprotocol.h +++ /dev/null @@ -1,375 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * ----------------------------------------------------------------------------- - */ -#ifndef _OZPROTOCOL_H -#define _OZPROTOCOL_H - -#define PACKED __packed - -#define OZ_ETHERTYPE 0x892e - -/* Status codes - */ -#define OZ_STATUS_SUCCESS 0 -#define OZ_STATUS_INVALID_PARAM 1 -#define OZ_STATUS_TOO_MANY_PDS 2 -#define OZ_STATUS_NOT_ALLOWED 4 -#define OZ_STATUS_SESSION_MISMATCH 5 -#define OZ_STATUS_SESSION_TEARDOWN 6 - -/* This is the generic element header. - Every element starts with this. - */ -struct oz_elt { - u8 type; - u8 length; -} PACKED; - -#define oz_next_elt(__elt) \ - (struct oz_elt *)((u8 *)((__elt) + 1) + (__elt)->length) - -/* Protocol element IDs. - */ -#define OZ_ELT_CONNECT_REQ 0x06 -#define OZ_ELT_CONNECT_RSP 0x07 -#define OZ_ELT_DISCONNECT 0x08 -#define OZ_ELT_UPDATE_PARAM_REQ 0x11 -#define OZ_ELT_FAREWELL_REQ 0x12 -#define OZ_ELT_APP_DATA 0x31 - -/* This is the Ozmo header which is the first Ozmo specific part - * of a frame and comes after the MAC header. - */ -struct oz_hdr { - u8 control; - u8 last_pkt_num; - u32 pkt_num; -} PACKED; - -#define OZ_PROTOCOL_VERSION 0x1 -/* Bits in the control field. */ -#define OZ_VERSION_MASK 0xc -#define OZ_VERSION_SHIFT 2 -#define OZ_F_ACK 0x10 -#define OZ_F_ISOC 0x20 -#define OZ_F_MORE_DATA 0x40 -#define OZ_F_ACK_REQUESTED 0x80 - -#define oz_get_prot_ver(__x) (((__x) & OZ_VERSION_MASK) >> OZ_VERSION_SHIFT) - -/* Used to select the bits of packet number to put in the last_pkt_num. - */ -#define OZ_LAST_PN_MASK 0x00ff - -#define OZ_LAST_PN_HALF_CYCLE 127 - -#define OZ_LATENCY_MASK 0xc0 -#define OZ_ONE_MS_LATENCY 0x40 -#define OZ_TEN_MS_LATENCY 0x80 - -/* Connect request data structure. - */ -struct oz_elt_connect_req { - u8 mode; - u8 resv1[16]; - u8 pd_info; - u8 session_id; - u8 presleep; - u8 ms_isoc_latency; - u8 host_vendor; - u8 keep_alive; - u16 apps; - u8 max_len_div16; - u8 ms_per_isoc; - u8 resv3[2]; -} PACKED; - -/* mode field bits. - */ -#define OZ_MODE_POLLED 0x0 -#define OZ_MODE_TRIGGERED 0x1 -#define OZ_MODE_MASK 0xf -#define OZ_F_ISOC_NO_ELTS 0x40 -#define OZ_F_ISOC_ANYTIME 0x80 -#define OZ_NO_ELTS_ANYTIME 0xc0 - -/* Keep alive field. - */ -#define OZ_KALIVE_TYPE_MASK 0xc0 -#define OZ_KALIVE_VALUE_MASK 0x3f -#define OZ_KALIVE_SPECIAL 0x00 -#define OZ_KALIVE_SECS 0x40 -#define OZ_KALIVE_MINS 0x80 -#define OZ_KALIVE_HOURS 0xc0 - -/* Connect response data structure. - */ -struct oz_elt_connect_rsp { - u8 mode; - u8 status; - u8 resv1[3]; - u8 session_id; - u16 apps; - u32 resv2; -} PACKED; - -struct oz_elt_farewell { - u8 ep_num; - u8 index; - u8 report[1]; -} PACKED; - -struct oz_elt_update_param { - u8 resv1[16]; - u8 presleep; - u8 resv2; - u8 host_vendor; - u8 keepalive; -} PACKED; - -/* Header common to all application elements. - */ -struct oz_app_hdr { - u8 app_id; - u8 elt_seq_num; -} PACKED; - -/* Values for app_id. - */ -#define OZ_APPID_USB 0x1 -#define OZ_APPID_SERIAL 0x4 -#define OZ_APPID_MAX OZ_APPID_SERIAL -#define OZ_NB_APPS (OZ_APPID_MAX+1) - -/* USB header common to all elements for the USB application. - * This header extends the oz_app_hdr and comes directly after - * the element header in a USB application. - */ -struct oz_usb_hdr { - u8 app_id; - u8 elt_seq_num; - u8 type; -} PACKED; - - - -/* USB requests element subtypes (type field of hs_usb_hdr). - */ -#define OZ_GET_DESC_REQ 1 -#define OZ_GET_DESC_RSP 2 -#define OZ_SET_CONFIG_REQ 3 -#define OZ_SET_CONFIG_RSP 4 -#define OZ_SET_INTERFACE_REQ 5 -#define OZ_SET_INTERFACE_RSP 6 -#define OZ_VENDOR_CLASS_REQ 7 -#define OZ_VENDOR_CLASS_RSP 8 -#define OZ_GET_STATUS_REQ 9 -#define OZ_GET_STATUS_RSP 10 -#define OZ_CLEAR_FEATURE_REQ 11 -#define OZ_CLEAR_FEATURE_RSP 12 -#define OZ_SET_FEATURE_REQ 13 -#define OZ_SET_FEATURE_RSP 14 -#define OZ_GET_CONFIGURATION_REQ 15 -#define OZ_GET_CONFIGURATION_RSP 16 -#define OZ_GET_INTERFACE_REQ 17 -#define OZ_GET_INTERFACE_RSP 18 -#define OZ_SYNCH_FRAME_REQ 19 -#define OZ_SYNCH_FRAME_RSP 20 -#define OZ_USB_ENDPOINT_DATA 23 - -#define OZ_REQD_D2H 0x80 - -struct oz_get_desc_req { - u8 app_id; - u8 elt_seq_num; - u8 type; - u8 req_id; - u16 offset; - u16 size; - u8 req_type; - u8 desc_type; - __le16 w_index; - u8 index; -} PACKED; - -/* Values for desc_type field. -*/ -#define OZ_DESC_DEVICE 0x01 -#define OZ_DESC_CONFIG 0x02 -#define OZ_DESC_STRING 0x03 - -/* Values for req_type field. - */ -#define OZ_RECP_MASK 0x1F -#define OZ_RECP_DEVICE 0x00 -#define OZ_RECP_INTERFACE 0x01 -#define OZ_RECP_ENDPOINT 0x02 - -#define OZ_REQT_MASK 0x60 -#define OZ_REQT_STD 0x00 -#define OZ_REQT_CLASS 0x20 -#define OZ_REQT_VENDOR 0x40 - -struct oz_get_desc_rsp { - u8 app_id; - u8 elt_seq_num; - u8 type; - u8 req_id; - __le16 offset; - __le16 total_size; - u8 rcode; - u8 data[1]; -} PACKED; - -struct oz_feature_req { - u8 app_id; - u8 elt_seq_num; - u8 type; - u8 req_id; - u8 recipient; - u8 index; - u16 feature; -} PACKED; - -struct oz_feature_rsp { - u8 app_id; - u8 elt_seq_num; - u8 type; - u8 req_id; - u8 rcode; -} PACKED; - -struct oz_set_config_req { - u8 app_id; - u8 elt_seq_num; - u8 type; - u8 req_id; - u8 index; -} PACKED; - -struct oz_set_config_rsp { - u8 app_id; - u8 elt_seq_num; - u8 type; - u8 req_id; - u8 rcode; -} PACKED; - -struct oz_set_interface_req { - u8 app_id; - u8 elt_seq_num; - u8 type; - u8 req_id; - u8 index; - u8 alternative; -} PACKED; - -struct oz_set_interface_rsp { - u8 app_id; - u8 elt_seq_num; - u8 type; - u8 req_id; - u8 rcode; -} PACKED; - -struct oz_get_interface_req { - u8 app_id; - u8 elt_seq_num; - u8 type; - u8 req_id; - u8 index; -} PACKED; - -struct oz_get_interface_rsp { - u8 app_id; - u8 elt_seq_num; - u8 type; - u8 req_id; - u8 rcode; - u8 alternative; -} PACKED; - -struct oz_vendor_class_req { - u8 app_id; - u8 elt_seq_num; - u8 type; - u8 req_id; - u8 req_type; - u8 request; - u16 value; - u16 index; - u8 data[1]; -} PACKED; - -struct oz_vendor_class_rsp { - u8 app_id; - u8 elt_seq_num; - u8 type; - u8 req_id; - u8 rcode; - u8 data[1]; -} PACKED; - -struct oz_data { - u8 app_id; - u8 elt_seq_num; - u8 type; - u8 endpoint; - u8 format; -} PACKED; - -struct oz_isoc_fixed { - u8 app_id; - u8 elt_seq_num; - u8 type; - u8 endpoint; - u8 format; - u8 unit_size; - u8 frame_number; - u8 data[1]; -} PACKED; - -struct oz_multiple_fixed { - u8 app_id; - u8 elt_seq_num; - u8 type; - u8 endpoint; - u8 format; - u8 unit_size; - u8 data[1]; -} PACKED; - -struct oz_fragmented { - u8 app_id; - u8 elt_seq_num; - u8 type; - u8 endpoint; - u8 format; - u16 total_size; - u16 offset; - u8 data[1]; -} PACKED; - -/* Note: the following does not get packaged in an element in the same way - * that other data formats are packaged. Instead the data is put in a frame - * directly after the oz_header and is the only permitted data in such a - * frame. The length of the data is directly determined from the frame size. - */ -struct oz_isoc_large { - u8 endpoint; - u8 format; - u8 ms_data; - u8 frame_number; -} PACKED; - -#define OZ_DATA_F_TYPE_MASK 0xF -#define OZ_DATA_F_MULTIPLE_FIXED 0x1 -#define OZ_DATA_F_MULTIPLE_VAR 0x2 -#define OZ_DATA_F_ISOC_FIXED 0x3 -#define OZ_DATA_F_ISOC_VAR 0x4 -#define OZ_DATA_F_FRAGMENTED 0x5 -#define OZ_DATA_F_ISOC_LARGE 0x7 - -#endif /* _OZPROTOCOL_H */ diff --git a/drivers/staging/ozwpan/ozurbparanoia.c b/drivers/staging/ozwpan/ozurbparanoia.c deleted file mode 100644 index cf6278a198a8..000000000000 --- a/drivers/staging/ozwpan/ozurbparanoia.c +++ /dev/null @@ -1,54 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * ----------------------------------------------------------------------------- - */ -#include <linux/usb.h> -#include "ozdbg.h" - -#ifdef WANT_URB_PARANOIA - -#include "ozurbparanoia.h" - -#define OZ_MAX_URBS 1000 -struct urb *g_urb_memory[OZ_MAX_URBS]; -int g_nb_urbs; -DEFINE_SPINLOCK(g_urb_mem_lock); - -void oz_remember_urb(struct urb *urb) -{ - unsigned long irq_state; - - spin_lock_irqsave(&g_urb_mem_lock, irq_state); - if (g_nb_urbs < OZ_MAX_URBS) { - g_urb_memory[g_nb_urbs++] = urb; - oz_dbg(ON, "urb up = %d %p\n", g_nb_urbs, urb); - } else { - oz_dbg(ON, "ERROR urb buffer full\n"); - } - spin_unlock_irqrestore(&g_urb_mem_lock, irq_state); -} - -/* - */ -int oz_forget_urb(struct urb *urb) -{ - unsigned long irq_state; - int i; - int rc = -1; - - spin_lock_irqsave(&g_urb_mem_lock, irq_state); - for (i = 0; i < g_nb_urbs; i++) { - if (g_urb_memory[i] == urb) { - rc = 0; - if (--g_nb_urbs > i) - memcpy(&g_urb_memory[i], &g_urb_memory[i+1], - (g_nb_urbs - i) * sizeof(struct urb *)); - oz_dbg(ON, "urb down = %d %p\n", g_nb_urbs, urb); - } - } - spin_unlock_irqrestore(&g_urb_mem_lock, irq_state); - return rc; -} -#endif /* #ifdef WANT_URB_PARANOIA */ - diff --git a/drivers/staging/ozwpan/ozurbparanoia.h b/drivers/staging/ozwpan/ozurbparanoia.h deleted file mode 100644 index 5080ea76f507..000000000000 --- a/drivers/staging/ozwpan/ozurbparanoia.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _OZURBPARANOIA_H -#define _OZURBPARANOIA_H -/* ----------------------------------------------------------------------------- - * Released under the GNU General Public License Version 2 (GPLv2). - * Copyright (c) 2011 Ozmo Inc - * ----------------------------------------------------------------------------- - */ - -#ifdef WANT_URB_PARANOIA -void oz_remember_urb(struct urb *urb); -int oz_forget_urb(struct urb *urb); -#else -static inline void oz_remember_urb(struct urb *urb) {} -static inline int oz_forget_urb(struct urb *urb) { return 0; } -#endif /* WANT_URB_PARANOIA */ - - -#endif /* _OZURBPARANOIA_H */ - diff --git a/drivers/staging/ozwpan/ozusbif.h b/drivers/staging/ozwpan/ozusbif.h deleted file mode 100644 index d2a6085345be..000000000000 --- a/drivers/staging/ozwpan/ozusbif.h +++ /dev/null @@ -1,43 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * ----------------------------------------------------------------------------- - */ -#ifndef _OZUSBIF_H -#define _OZUSBIF_H - -#include <linux/usb.h> - -/* Reference counting functions. - */ -void oz_usb_get(void *hpd); -void oz_usb_put(void *hpd); - -/* Stream functions. - */ -int oz_usb_stream_create(void *hpd, u8 ep_num); -int oz_usb_stream_delete(void *hpd, u8 ep_num); - -/* Request functions. - */ -int oz_usb_control_req(void *hpd, u8 req_id, struct usb_ctrlrequest *setup, - const u8 *data, int data_len); -int oz_usb_get_desc_req(void *hpd, u8 req_id, u8 req_type, u8 desc_type, - u8 index, __le16 windex, int offset, int len); -int oz_usb_send_isoc(void *hpd, u8 ep_num, struct urb *urb); -void oz_usb_request_heartbeat(void *hpd); - -/* Confirmation functions. - */ -void oz_hcd_get_desc_cnf(void *hport, u8 req_id, u8 status, - const u8 *desc, u8 length, u16 offset, u16 total_size); -void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, - const u8 *data, int data_len); - -/* Indication functions. - */ -void oz_hcd_data_ind(void *hport, u8 endpoint, const u8 *data, int data_len); - -int oz_hcd_heartbeat(void *hport); - -#endif /* _OZUSBIF_H */ diff --git a/drivers/staging/ozwpan/ozusbsvc.c b/drivers/staging/ozwpan/ozusbsvc.c deleted file mode 100644 index bf15dc301cb5..000000000000 --- a/drivers/staging/ozwpan/ozusbsvc.c +++ /dev/null @@ -1,263 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * - * This file provides protocol independent part of the implementation of the USB - * service for a PD. - * The implementation of this service is split into two parts the first of which - * is protocol independent and the second contains protocol specific details. - * This split is to allow alternative protocols to be defined. - * The implementation of this service uses ozhcd.c to implement a USB HCD. - * ----------------------------------------------------------------------------- - */ - -#include <linux/module.h> -#include <linux/timer.h> -#include <linux/sched.h> -#include <linux/netdevice.h> -#include <linux/errno.h> -#include <linux/input.h> -#include <asm/unaligned.h> -#include "ozdbg.h" -#include "ozprotocol.h" -#include "ozeltbuf.h" -#include "ozpd.h" -#include "ozproto.h" -#include "ozusbif.h" -#include "ozhcd.h" -#include "ozusbsvc.h" - -/* - * This is called once when the driver is loaded to initialise the USB service. - * Context: process - */ -int oz_usb_init(void) -{ - return oz_hcd_init(); -} - -/* - * This is called once when the driver is unloaded to terminate the USB service. - * Context: process - */ -void oz_usb_term(void) -{ - oz_hcd_term(); -} - -/* - * This is called when the USB service is started or resumed for a PD. - * Context: softirq - */ -int oz_usb_start(struct oz_pd *pd, int resume) -{ - int rc = 0; - struct oz_usb_ctx *usb_ctx; - struct oz_usb_ctx *old_ctx; - - if (resume) { - oz_dbg(ON, "USB service resumed\n"); - return 0; - } - oz_dbg(ON, "USB service started\n"); - /* Create a USB context in case we need one. If we find the PD already - * has a USB context then we will destroy it. - */ - usb_ctx = kzalloc(sizeof(struct oz_usb_ctx), GFP_ATOMIC); - if (usb_ctx == NULL) - return -ENOMEM; - atomic_set(&usb_ctx->ref_count, 1); - usb_ctx->pd = pd; - usb_ctx->stopped = 0; - /* Install the USB context if the PD doesn't already have one. - * If it does already have one then destroy the one we have just - * created. - */ - spin_lock_bh(&pd->app_lock[OZ_APPID_USB]); - old_ctx = pd->app_ctx[OZ_APPID_USB]; - if (old_ctx == NULL) - pd->app_ctx[OZ_APPID_USB] = usb_ctx; - oz_usb_get(pd->app_ctx[OZ_APPID_USB]); - spin_unlock_bh(&pd->app_lock[OZ_APPID_USB]); - if (old_ctx) { - oz_dbg(ON, "Already have USB context\n"); - kfree(usb_ctx); - usb_ctx = old_ctx; - } else if (usb_ctx) { - /* Take a reference to the PD. This will be released when - * the USB context is destroyed. - */ - oz_pd_get(pd); - } - /* If we already had a USB context and had obtained a port from - * the USB HCD then just reset the port. If we didn't have a port - * then report the arrival to the USB HCD so we get one. - */ - if (usb_ctx->hport) { - oz_hcd_pd_reset(usb_ctx, usb_ctx->hport); - } else { - usb_ctx->hport = oz_hcd_pd_arrived(usb_ctx); - if (usb_ctx->hport == NULL) { - oz_dbg(ON, "USB hub returned null port\n"); - spin_lock_bh(&pd->app_lock[OZ_APPID_USB]); - pd->app_ctx[OZ_APPID_USB] = NULL; - spin_unlock_bh(&pd->app_lock[OZ_APPID_USB]); - oz_usb_put(usb_ctx); - rc = -1; - } - } - oz_usb_put(usb_ctx); - return rc; -} - -/* - * This is called when the USB service is stopped or paused for a PD. - * Context: softirq or process - */ -void oz_usb_stop(struct oz_pd *pd, int pause) -{ - struct oz_usb_ctx *usb_ctx; - - if (pause) { - oz_dbg(ON, "USB service paused\n"); - return; - } - spin_lock_bh(&pd->app_lock[OZ_APPID_USB]); - usb_ctx = (struct oz_usb_ctx *) pd->app_ctx[OZ_APPID_USB]; - pd->app_ctx[OZ_APPID_USB] = NULL; - spin_unlock_bh(&pd->app_lock[OZ_APPID_USB]); - if (usb_ctx) { - struct timespec ts, now; - - getnstimeofday(&ts); - oz_dbg(ON, "USB service stopping...\n"); - usb_ctx->stopped = 1; - /* At this point the reference count on the usb context should - * be 2 - one from when we created it and one from the hcd - * which claims a reference. Since stopped = 1 no one else - * should get in but someone may already be in. So wait - * until they leave but timeout after 1 second. - */ - while ((atomic_read(&usb_ctx->ref_count) > 2)) { - getnstimeofday(&now); - /*Approx 1 Sec. this is not perfect calculation*/ - if (now.tv_sec != ts.tv_sec) - break; - } - oz_dbg(ON, "USB service stopped\n"); - oz_hcd_pd_departed(usb_ctx->hport); - /* Release the reference taken in oz_usb_start. - */ - oz_usb_put(usb_ctx); - } -} - -/* - * This increments the reference count of the context area for a specific PD. - * This ensures this context area does not disappear while still in use. - * Context: softirq - */ -void oz_usb_get(void *hpd) -{ - struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd; - - atomic_inc(&usb_ctx->ref_count); -} - -/* - * This decrements the reference count of the context area for a specific PD - * and destroys the context area if the reference count becomes zero. - * Context: irq or process - */ -void oz_usb_put(void *hpd) -{ - struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd; - - if (atomic_dec_and_test(&usb_ctx->ref_count)) { - oz_dbg(ON, "Dealloc USB context\n"); - oz_pd_put(usb_ctx->pd); - kfree(usb_ctx); - } -} - -/* - * Context: softirq - */ -int oz_usb_heartbeat(struct oz_pd *pd) -{ - struct oz_usb_ctx *usb_ctx; - int rc = 0; - - spin_lock_bh(&pd->app_lock[OZ_APPID_USB]); - usb_ctx = (struct oz_usb_ctx *) pd->app_ctx[OZ_APPID_USB]; - if (usb_ctx) - oz_usb_get(usb_ctx); - spin_unlock_bh(&pd->app_lock[OZ_APPID_USB]); - if (usb_ctx == NULL) - return rc; - if (usb_ctx->stopped) - goto done; - if (usb_ctx->hport) - if (oz_hcd_heartbeat(usb_ctx->hport)) - rc = 1; -done: - oz_usb_put(usb_ctx); - return rc; -} - -/* - * Context: softirq - */ -int oz_usb_stream_create(void *hpd, u8 ep_num) -{ - struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd; - struct oz_pd *pd = usb_ctx->pd; - - oz_dbg(ON, "%s: (0x%x)\n", __func__, ep_num); - if (pd->mode & OZ_F_ISOC_NO_ELTS) { - oz_isoc_stream_create(pd, ep_num); - } else { - oz_pd_get(pd); - if (oz_elt_stream_create(&pd->elt_buff, ep_num, - 4*pd->max_tx_size)) { - oz_pd_put(pd); - return -1; - } - } - return 0; -} - -/* - * Context: softirq - */ -int oz_usb_stream_delete(void *hpd, u8 ep_num) -{ - struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd; - - if (usb_ctx) { - struct oz_pd *pd = usb_ctx->pd; - - if (pd) { - oz_dbg(ON, "%s: (0x%x)\n", __func__, ep_num); - if (pd->mode & OZ_F_ISOC_NO_ELTS) { - oz_isoc_stream_delete(pd, ep_num); - } else { - if (oz_elt_stream_delete(&pd->elt_buff, ep_num)) - return -1; - oz_pd_put(pd); - } - } - } - return 0; -} - -/* - * Context: softirq or process - */ -void oz_usb_request_heartbeat(void *hpd) -{ - struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd; - - if (usb_ctx && usb_ctx->pd) - oz_pd_request_heartbeat(usb_ctx->pd); -} diff --git a/drivers/staging/ozwpan/ozusbsvc.h b/drivers/staging/ozwpan/ozusbsvc.h deleted file mode 100644 index 58e05a59be31..000000000000 --- a/drivers/staging/ozwpan/ozusbsvc.h +++ /dev/null @@ -1,32 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * ----------------------------------------------------------------------------- - */ -#ifndef _OZUSBSVC_H -#define _OZUSBSVC_H - -/*------------------------------------------------------------------------------ - * Per PD context info stored in application context area of PD. - * This object is reference counted to ensure it doesn't disappear while - * still in use. - */ -struct oz_usb_ctx { - atomic_t ref_count; - u8 tx_seq_num; - u8 rx_seq_num; - struct oz_pd *pd; - void *hport; - int stopped; -}; - -int oz_usb_init(void); -void oz_usb_term(void); -int oz_usb_start(struct oz_pd *pd, int resume); -void oz_usb_stop(struct oz_pd *pd, int pause); -void oz_usb_rx(struct oz_pd *pd, struct oz_elt *elt); -int oz_usb_heartbeat(struct oz_pd *pd); -void oz_usb_farewell(struct oz_pd *pd, u8 ep_num, u8 *data, u8 len); - -#endif /* _OZUSBSVC_H */ - diff --git a/drivers/staging/ozwpan/ozusbsvc1.c b/drivers/staging/ozwpan/ozusbsvc1.c deleted file mode 100644 index b6cfecbeabf7..000000000000 --- a/drivers/staging/ozwpan/ozusbsvc1.c +++ /dev/null @@ -1,472 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * - * This file implements the protocol specific parts of the USB service for a PD. - * ----------------------------------------------------------------------------- - */ -#include <linux/module.h> -#include <linux/timer.h> -#include <linux/sched.h> -#include <linux/netdevice.h> -#include <linux/errno.h> -#include <linux/input.h> -#include <asm/unaligned.h> -#include "ozdbg.h" -#include "ozprotocol.h" -#include "ozeltbuf.h" -#include "ozpd.h" -#include "ozproto.h" -#include "ozusbif.h" -#include "ozhcd.h" -#include "ozusbsvc.h" - -#define MAX_ISOC_FIXED_DATA (253-sizeof(struct oz_isoc_fixed)) - -/* - * Context: softirq - */ -static int oz_usb_submit_elt(struct oz_elt_buf *eb, struct oz_elt_info *ei, - struct oz_usb_ctx *usb_ctx, u8 strid, u8 isoc) -{ - int ret; - struct oz_elt *elt = (struct oz_elt *)ei->data; - struct oz_app_hdr *app_hdr = (struct oz_app_hdr *)(elt+1); - - elt->type = OZ_ELT_APP_DATA; - ei->app_id = OZ_APPID_USB; - ei->length = elt->length + sizeof(struct oz_elt); - app_hdr->app_id = OZ_APPID_USB; - spin_lock_bh(&eb->lock); - if (isoc == 0) { - app_hdr->elt_seq_num = usb_ctx->tx_seq_num++; - if (usb_ctx->tx_seq_num == 0) - usb_ctx->tx_seq_num = 1; - } - ret = oz_queue_elt_info(eb, isoc, strid, ei); - if (ret) - oz_elt_info_free(eb, ei); - spin_unlock_bh(&eb->lock); - return ret; -} - -/* - * Context: softirq - */ -int oz_usb_get_desc_req(void *hpd, u8 req_id, u8 req_type, u8 desc_type, - u8 index, __le16 windex, int offset, int len) -{ - struct oz_usb_ctx *usb_ctx = hpd; - struct oz_pd *pd = usb_ctx->pd; - struct oz_elt *elt; - struct oz_get_desc_req *body; - struct oz_elt_buf *eb = &pd->elt_buff; - struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff); - - oz_dbg(ON, " req_type = 0x%x\n", req_type); - oz_dbg(ON, " desc_type = 0x%x\n", desc_type); - oz_dbg(ON, " index = 0x%x\n", index); - oz_dbg(ON, " windex = 0x%x\n", windex); - oz_dbg(ON, " offset = 0x%x\n", offset); - oz_dbg(ON, " len = 0x%x\n", len); - if (len > 200) - len = 200; - if (ei == NULL) - return -1; - elt = (struct oz_elt *)ei->data; - elt->length = sizeof(struct oz_get_desc_req); - body = (struct oz_get_desc_req *)(elt+1); - body->type = OZ_GET_DESC_REQ; - body->req_id = req_id; - put_unaligned(cpu_to_le16(offset), &body->offset); - put_unaligned(cpu_to_le16(len), &body->size); - body->req_type = req_type; - body->desc_type = desc_type; - body->w_index = windex; - body->index = index; - return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0); -} - -/* - * Context: tasklet - */ -static int oz_usb_set_config_req(void *hpd, u8 req_id, u8 index) -{ - struct oz_usb_ctx *usb_ctx = hpd; - struct oz_pd *pd = usb_ctx->pd; - struct oz_elt *elt; - struct oz_elt_buf *eb = &pd->elt_buff; - struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff); - struct oz_set_config_req *body; - - if (ei == NULL) - return -1; - elt = (struct oz_elt *)ei->data; - elt->length = sizeof(struct oz_set_config_req); - body = (struct oz_set_config_req *)(elt+1); - body->type = OZ_SET_CONFIG_REQ; - body->req_id = req_id; - body->index = index; - return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0); -} - -/* - * Context: tasklet - */ -static int oz_usb_set_interface_req(void *hpd, u8 req_id, u8 index, u8 alt) -{ - struct oz_usb_ctx *usb_ctx = hpd; - struct oz_pd *pd = usb_ctx->pd; - struct oz_elt *elt; - struct oz_elt_buf *eb = &pd->elt_buff; - struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff); - struct oz_set_interface_req *body; - - if (ei == NULL) - return -1; - elt = (struct oz_elt *)ei->data; - elt->length = sizeof(struct oz_set_interface_req); - body = (struct oz_set_interface_req *)(elt+1); - body->type = OZ_SET_INTERFACE_REQ; - body->req_id = req_id; - body->index = index; - body->alternative = alt; - return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0); -} - -/* - * Context: tasklet - */ -static int oz_usb_set_clear_feature_req(void *hpd, u8 req_id, u8 type, - u8 recipient, u8 index, __le16 feature) -{ - struct oz_usb_ctx *usb_ctx = hpd; - struct oz_pd *pd = usb_ctx->pd; - struct oz_elt *elt; - struct oz_elt_buf *eb = &pd->elt_buff; - struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff); - struct oz_feature_req *body; - - if (ei == NULL) - return -1; - elt = (struct oz_elt *)ei->data; - elt->length = sizeof(struct oz_feature_req); - body = (struct oz_feature_req *)(elt+1); - body->type = type; - body->req_id = req_id; - body->recipient = recipient; - body->index = index; - put_unaligned(feature, &body->feature); - return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0); -} - -/* - * Context: tasklet - */ -static int oz_usb_vendor_class_req(void *hpd, u8 req_id, u8 req_type, - u8 request, __le16 value, __le16 index, const u8 *data, int data_len) -{ - struct oz_usb_ctx *usb_ctx = hpd; - struct oz_pd *pd = usb_ctx->pd; - struct oz_elt *elt; - struct oz_elt_buf *eb = &pd->elt_buff; - struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff); - struct oz_vendor_class_req *body; - - if (ei == NULL) - return -1; - elt = (struct oz_elt *)ei->data; - elt->length = sizeof(struct oz_vendor_class_req) - 1 + data_len; - body = (struct oz_vendor_class_req *)(elt+1); - body->type = OZ_VENDOR_CLASS_REQ; - body->req_id = req_id; - body->req_type = req_type; - body->request = request; - put_unaligned(value, &body->value); - put_unaligned(index, &body->index); - if (data_len) - memcpy(body->data, data, data_len); - return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0); -} - -/* - * Context: tasklet - */ -int oz_usb_control_req(void *hpd, u8 req_id, struct usb_ctrlrequest *setup, - const u8 *data, int data_len) -{ - unsigned wvalue = le16_to_cpu(setup->wValue); - unsigned windex = le16_to_cpu(setup->wIndex); - unsigned wlength = le16_to_cpu(setup->wLength); - int rc = 0; - - if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { - switch (setup->bRequest) { - case USB_REQ_GET_DESCRIPTOR: - rc = oz_usb_get_desc_req(hpd, req_id, - setup->bRequestType, (u8)(wvalue>>8), - (u8)wvalue, setup->wIndex, 0, wlength); - break; - case USB_REQ_SET_CONFIGURATION: - rc = oz_usb_set_config_req(hpd, req_id, (u8)wvalue); - break; - case USB_REQ_SET_INTERFACE: { - u8 if_num = (u8)windex; - u8 alt = (u8)wvalue; - - rc = oz_usb_set_interface_req(hpd, req_id, - if_num, alt); - } - break; - case USB_REQ_SET_FEATURE: - rc = oz_usb_set_clear_feature_req(hpd, req_id, - OZ_SET_FEATURE_REQ, - setup->bRequestType & 0xf, (u8)windex, - setup->wValue); - break; - case USB_REQ_CLEAR_FEATURE: - rc = oz_usb_set_clear_feature_req(hpd, req_id, - OZ_CLEAR_FEATURE_REQ, - setup->bRequestType & 0xf, - (u8)windex, setup->wValue); - break; - } - } else { - rc = oz_usb_vendor_class_req(hpd, req_id, setup->bRequestType, - setup->bRequest, setup->wValue, setup->wIndex, - data, data_len); - } - return rc; -} - -/* - * Context: softirq - */ -int oz_usb_send_isoc(void *hpd, u8 ep_num, struct urb *urb) -{ - struct oz_usb_ctx *usb_ctx = hpd; - struct oz_pd *pd = usb_ctx->pd; - struct oz_elt_buf *eb; - int i; - int hdr_size; - u8 *data; - struct usb_iso_packet_descriptor *desc; - - if (pd->mode & OZ_F_ISOC_NO_ELTS) { - for (i = 0; i < urb->number_of_packets; i++) { - u8 *data; - - desc = &urb->iso_frame_desc[i]; - data = ((u8 *)urb->transfer_buffer)+desc->offset; - oz_send_isoc_unit(pd, ep_num, data, desc->length); - } - return 0; - } - - hdr_size = sizeof(struct oz_isoc_fixed) - 1; - eb = &pd->elt_buff; - i = 0; - while (i < urb->number_of_packets) { - struct oz_elt_info *ei = oz_elt_info_alloc(eb); - struct oz_elt *elt; - struct oz_isoc_fixed *body; - int unit_count; - int unit_size; - int rem; - - if (ei == NULL) - return -1; - rem = MAX_ISOC_FIXED_DATA; - elt = (struct oz_elt *)ei->data; - body = (struct oz_isoc_fixed *)(elt + 1); - body->type = OZ_USB_ENDPOINT_DATA; - body->endpoint = ep_num; - body->format = OZ_DATA_F_ISOC_FIXED; - unit_size = urb->iso_frame_desc[i].length; - body->unit_size = (u8)unit_size; - data = ((u8 *)(elt+1)) + hdr_size; - unit_count = 0; - while (i < urb->number_of_packets) { - desc = &urb->iso_frame_desc[i]; - if ((unit_size == desc->length) && - (desc->length <= rem)) { - memcpy(data, ((u8 *)urb->transfer_buffer) + - desc->offset, unit_size); - data += unit_size; - rem -= unit_size; - unit_count++; - desc->status = 0; - desc->actual_length = desc->length; - i++; - } else { - break; - } - } - elt->length = hdr_size + MAX_ISOC_FIXED_DATA - rem; - /* Store the number of units in body->frame_number for the - * moment. This field will be correctly determined before - * the element is sent. */ - body->frame_number = (u8)unit_count; - oz_usb_submit_elt(eb, ei, usb_ctx, ep_num, - pd->mode & OZ_F_ISOC_ANYTIME); - } - return 0; -} - -/* - * Context: softirq-serialized - */ -static void oz_usb_handle_ep_data(struct oz_usb_ctx *usb_ctx, - struct oz_usb_hdr *usb_hdr, int len) -{ - struct oz_data *data_hdr = (struct oz_data *)usb_hdr; - - switch (data_hdr->format) { - case OZ_DATA_F_MULTIPLE_FIXED: { - struct oz_multiple_fixed *body = - (struct oz_multiple_fixed *)data_hdr; - u8 *data = body->data; - unsigned int n; - - if (!body->unit_size || - len < sizeof(struct oz_multiple_fixed) - 1) - break; - n = (len - (sizeof(struct oz_multiple_fixed) - 1)) - / body->unit_size; - while (n--) { - oz_hcd_data_ind(usb_ctx->hport, body->endpoint, - data, body->unit_size); - data += body->unit_size; - } - } - break; - case OZ_DATA_F_ISOC_FIXED: { - struct oz_isoc_fixed *body = - (struct oz_isoc_fixed *)data_hdr; - int data_len; - int unit_size = body->unit_size; - u8 *data = body->data; - int count; - int i; - - if (len < sizeof(struct oz_isoc_fixed) - 1) - break; - data_len = len - (sizeof(struct oz_isoc_fixed) - 1); - - if (!unit_size) - break; - count = data_len/unit_size; - for (i = 0; i < count; i++) { - oz_hcd_data_ind(usb_ctx->hport, - body->endpoint, data, unit_size); - data += unit_size; - } - } - break; - } - -} - -/* - * This is called when the PD has received a USB element. The type of element - * is determined and is then passed to an appropriate handler function. - * Context: softirq-serialized - */ -void oz_usb_rx(struct oz_pd *pd, struct oz_elt *elt) -{ - struct oz_usb_hdr *usb_hdr = (struct oz_usb_hdr *)(elt + 1); - struct oz_usb_ctx *usb_ctx; - - spin_lock_bh(&pd->app_lock[OZ_APPID_USB]); - usb_ctx = (struct oz_usb_ctx *)pd->app_ctx[OZ_APPID_USB]; - if (usb_ctx) - oz_usb_get(usb_ctx); - spin_unlock_bh(&pd->app_lock[OZ_APPID_USB]); - if (usb_ctx == NULL) - return; /* Context has gone so nothing to do. */ - if (usb_ctx->stopped) - goto done; - /* If sequence number is non-zero then check it is not a duplicate. - * Zero sequence numbers are always accepted. - */ - if (usb_hdr->elt_seq_num != 0) { - if (((usb_ctx->rx_seq_num - usb_hdr->elt_seq_num) & 0x80) == 0) - /* Reject duplicate element. */ - goto done; - } - usb_ctx->rx_seq_num = usb_hdr->elt_seq_num; - switch (usb_hdr->type) { - case OZ_GET_DESC_RSP: { - struct oz_get_desc_rsp *body = - (struct oz_get_desc_rsp *)usb_hdr; - u16 offs, total_size; - u8 data_len; - - if (elt->length < sizeof(struct oz_get_desc_rsp) - 1) - break; - data_len = elt->length - - (sizeof(struct oz_get_desc_rsp) - 1); - offs = le16_to_cpu(get_unaligned(&body->offset)); - total_size = - le16_to_cpu(get_unaligned(&body->total_size)); - oz_dbg(ON, "USB_REQ_GET_DESCRIPTOR - cnf\n"); - oz_hcd_get_desc_cnf(usb_ctx->hport, body->req_id, - body->rcode, body->data, - data_len, offs, total_size); - } - break; - case OZ_SET_CONFIG_RSP: { - struct oz_set_config_rsp *body = - (struct oz_set_config_rsp *)usb_hdr; - oz_hcd_control_cnf(usb_ctx->hport, body->req_id, - body->rcode, NULL, 0); - } - break; - case OZ_SET_INTERFACE_RSP: { - struct oz_set_interface_rsp *body = - (struct oz_set_interface_rsp *)usb_hdr; - oz_hcd_control_cnf(usb_ctx->hport, - body->req_id, body->rcode, NULL, 0); - } - break; - case OZ_VENDOR_CLASS_RSP: { - struct oz_vendor_class_rsp *body = - (struct oz_vendor_class_rsp *)usb_hdr; - - if (elt->length < - sizeof(struct oz_vendor_class_rsp) - 1) - break; - - oz_hcd_control_cnf(usb_ctx->hport, body->req_id, - body->rcode, body->data, elt->length- - sizeof(struct oz_vendor_class_rsp)+1); - } - break; - case OZ_USB_ENDPOINT_DATA: - oz_usb_handle_ep_data(usb_ctx, usb_hdr, elt->length); - break; - } -done: - oz_usb_put(usb_ctx); -} - -/* - * Context: softirq, process - */ -void oz_usb_farewell(struct oz_pd *pd, u8 ep_num, u8 *data, u8 len) -{ - struct oz_usb_ctx *usb_ctx; - - spin_lock_bh(&pd->app_lock[OZ_APPID_USB]); - usb_ctx = (struct oz_usb_ctx *)pd->app_ctx[OZ_APPID_USB]; - if (usb_ctx) - oz_usb_get(usb_ctx); - spin_unlock_bh(&pd->app_lock[OZ_APPID_USB]); - if (usb_ctx == NULL) - return; /* Context has gone so nothing to do. */ - if (!usb_ctx->stopped) { - oz_dbg(ON, "Farewell indicated ep = 0x%x\n", ep_num); - oz_hcd_data_ind(usb_ctx->hport, ep_num, data, len); - } - oz_usb_put(usb_ctx); -} diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index bda208da514e..3e9ee7ee6be2 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -781,14 +781,18 @@ static void long_sleep(int ms) schedule_timeout_interruptible(msecs_to_jiffies(ms)); } -/* send a serial byte to the LCD panel. The caller is responsible for locking - if needed. */ +/* + * send a serial byte to the LCD panel. The caller is responsible for locking + * if needed. + */ static void lcd_send_serial(int byte) { int bit; - /* the data bit is set on D0, and the clock on STROBE. - * LCD reads D0 on STROBE's rising edge. */ + /* + * the data bit is set on D0, and the clock on STROBE. + * LCD reads D0 on STROBE's rising edge. + */ for (bit = 0; bit < 8; bit++) { bits.cl = BIT_CLR; /* CLK low */ panel_set_bits(); diff --git a/drivers/staging/rtl8188eu/core/rtw_debug.c b/drivers/staging/rtl8188eu/core/rtw_debug.c index bc3fe10ff247..993c7db87a1a 100644 --- a/drivers/staging/rtl8188eu/core/rtw_debug.c +++ b/drivers/staging/rtl8188eu/core/rtw_debug.c @@ -219,6 +219,7 @@ int proc_get_ht_option(char *page, char **start, struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); int len = 0; + len += snprintf(page + len, count - len, "ht_option=%d\n", pmlmepriv->htpriv.ht_option); *eof = 1; return len; @@ -588,6 +589,7 @@ int proc_set_rx_signal(struct file *file, const char __user *buffer, if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { int num = sscanf(tmp, "%u %u", &is_signal_dbg, &signal_strength); + is_signal_dbg = is_signal_dbg == 0 ? 0 : 1; if (is_signal_dbg && num != 2) return count; @@ -917,7 +919,7 @@ int proc_get_best_channel(char *page, char **start, /* 5G */ if (pmlmeext->channel_set[i].ChannelNum >= 36 && pmlmeext->channel_set[i].ChannelNum < 140) { - /* Find primary channel */ + /* Find primary channel */ if (((pmlmeext->channel_set[i].ChannelNum - 36) % 8 == 0) && (pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_5G].rx_count)) { index_5G = i; @@ -927,7 +929,7 @@ int proc_get_best_channel(char *page, char **start, if (pmlmeext->channel_set[i].ChannelNum >= 149 && pmlmeext->channel_set[i].ChannelNum < 165) { - /* find primary channel */ + /* find primary channel */ if (((pmlmeext->channel_set[i].ChannelNum - 149) % 8 == 0) && (pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_5G].rx_count)) { index_5G = i; diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index dbaba2c6cce5..7b99ea91a9e6 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -551,7 +551,7 @@ int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) bContinual = false; } } else if (ReadState & PG_STATE_DATA) { - /* Data section Read ------------- */ + /* Data section Read ------------- */ efuse_WordEnableDataRead(hworden, tmpdata, data); efuse_addr = efuse_addr + (word_cnts*2)+1; ReadState = PG_STATE_HEADER; diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index d43e8672d86e..c3c582881a09 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -1044,7 +1044,7 @@ enum parse_res rtw_ieee802_11_parse_elems(u8 *start, uint len, elems->timeout_int = pos; elems->timeout_int_len = elen; break; - case WLAN_EID_HT_CAP: + case WLAN_EID_HT_CAPABILITY: elems->ht_capabilities = pos; elems->ht_capabilities_len = elen; break; diff --git a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c index 8c05cb021c46..22f5b45f5f7f 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c +++ b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c @@ -183,7 +183,7 @@ u8 rtw_set_802_11_bssid(struct adapter *padapter, u8 *bssid) if (check_fwstate(pmlmepriv, _FW_LINKED) == true) rtw_indicate_disconnect(padapter); - rtw_free_assoc_resources(padapter, 1); + rtw_free_assoc_resources(padapter); if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) { _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE); @@ -271,7 +271,7 @@ u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid) if (check_fwstate(pmlmepriv, _FW_LINKED) == true) rtw_indicate_disconnect(padapter); - rtw_free_assoc_resources(padapter, 1); + rtw_free_assoc_resources(padapter); if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) { _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE); @@ -293,7 +293,7 @@ u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid) if (check_fwstate(pmlmepriv, _FW_LINKED) == true) rtw_indicate_disconnect(padapter); - rtw_free_assoc_resources(padapter, 1); + rtw_free_assoc_resources(padapter); if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) { _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE); @@ -366,7 +366,7 @@ u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter, if ((check_fwstate(pmlmepriv, _FW_LINKED)) || (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))) - rtw_free_assoc_resources(padapter, 1); + rtw_free_assoc_resources(padapter); if ((*pold_state == Ndis802_11Infrastructure) || (*pold_state == Ndis802_11IBSS)) { if (check_fwstate(pmlmepriv, _FW_LINKED) == true) @@ -415,7 +415,7 @@ u8 rtw_set_802_11_disassociate(struct adapter *padapter) rtw_disassoc_cmd(padapter, 0, true); rtw_indicate_disconnect(padapter); - rtw_free_assoc_resources(padapter, 1); + rtw_free_assoc_resources(padapter); rtw_pwr_wakeup(padapter); } diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index 2b599e3c0785..2b917a18e228 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -693,8 +693,8 @@ void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf) pmlmepriv->to_join = false; s_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv); if (_SUCCESS == s_ret) { - mod_timer(&pmlmepriv->assoc_timer, - jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT)); + mod_timer(&pmlmepriv->assoc_timer, + jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT)); } else if (s_ret == 2) { /* there is no need to wait for join */ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); rtw_indicate_connect(adapter); @@ -704,7 +704,7 @@ void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf) if (--pmlmepriv->to_roaming == 0 || _SUCCESS != rtw_sitesurvey_cmd(adapter, &pmlmepriv->assoc_ssid, 1, NULL, 0)) { pmlmepriv->to_roaming = 0; - rtw_free_assoc_resources(adapter, 1); + rtw_free_assoc_resources(adapter); rtw_indicate_disconnect(adapter); } else { pmlmepriv->to_join = true; @@ -758,7 +758,19 @@ static void free_scanqueue(struct mlme_priv *pmlmepriv) /* *rtw_free_assoc_resources: the caller has to lock pmlmepriv->lock */ -void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue) +void rtw_free_assoc_resources(struct adapter *adapter) +{ + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + + spin_lock_bh(&pmlmepriv->scanned_queue.lock); + rtw_free_assoc_resources_locked(adapter); + spin_unlock_bh(&pmlmepriv->scanned_queue.lock); +} + +/* +*rtw_free_assoc_resources_locked: the caller has to lock pmlmepriv->lock +*/ +void rtw_free_assoc_resources_locked(struct adapter *adapter) { struct wlan_network *pwlan = NULL; struct mlme_priv *pmlmepriv = &adapter->mlmepriv; @@ -793,8 +805,6 @@ void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue) rtw_init_bcmc_stainfo(adapter); } - if (lock_scanned_queue) - spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress); if (pwlan) @@ -805,8 +815,6 @@ void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue) if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) && (adapter->stapriv.asoc_sta_count == 1))) rtw_free_network_nolock(pmlmepriv, pwlan); - if (lock_scanned_queue) - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); pmlmepriv->key_mask = 0; } @@ -1302,7 +1310,7 @@ void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf) rtw_free_uc_swdec_pending_queue(adapter); - rtw_free_assoc_resources(adapter, 1); + rtw_free_assoc_resources(adapter); rtw_indicate_disconnect(adapter); spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); /* remove the network entry in scanned_queue */ @@ -1557,7 +1565,7 @@ int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv) rtw_disassoc_cmd(adapter, 0, true); rtw_indicate_disconnect(adapter); - rtw_free_assoc_resources(adapter, 0); + rtw_free_assoc_resources_locked(adapter); } rtw_hal_get_def_var(adapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &(supp_ant_div)); diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index ba8f9aa5d259..935b48eef8b1 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -1096,7 +1096,7 @@ static void issue_assocreq(struct adapter *padapter) /* Check if the AP's supported rates are also supported by STA. */ for (j = 0; j < sta_bssrate_len; j++) { - /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */ + /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */ if ((pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK) == (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)) break; @@ -2932,7 +2932,7 @@ static unsigned int OnAuthClient(struct adapter *padapter, if (seq == 2) { if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) { - /* legendary shared system */ + /* legendary shared system */ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len, pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_); @@ -4155,8 +4155,8 @@ static void _mgt_dispatcher(struct adapter *padapter, struct mlme_handler *ptabl u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; u8 *pframe = precv_frame->rx_data; - if (ptable->func) { - /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */ + if (ptable->func) { + /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */ if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) && memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) return; diff --git a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c index a2b54de21ed7..9765946466ab 100644 --- a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c +++ b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c @@ -70,7 +70,7 @@ static int rtw_hw_suspend(struct adapter *padapter) } } /* s2-3. */ - rtw_free_assoc_resources(padapter, 1); + rtw_free_assoc_resources(padapter); /* s2-4. */ rtw_free_network_queue(padapter, true); diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index 8501eb898824..44eeb03213e6 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -74,10 +74,8 @@ int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter) precvpriv->pallocated_frame_buf = vzalloc(NR_RECVFRAME * sizeof(struct recv_frame) + RXFRAME_ALIGN_SZ); - if (precvpriv->pallocated_frame_buf == NULL) { - res = _FAIL; - goto exit; - } + if (!precvpriv->pallocated_frame_buf) + return _FAIL; precvpriv->precv_frame_buf = (u8 *)N_BYTE_ALIGMENT((size_t)(precvpriv->pallocated_frame_buf), RXFRAME_ALIGN_SZ); @@ -89,7 +87,7 @@ int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter) list_add_tail(&(precvframe->list), &(precvpriv->free_recv_queue.queue)); - res = rtw_os_recv_resource_alloc(padapter, precvframe); + rtw_os_recv_resource_alloc(precvframe); precvframe->len = 0; @@ -107,8 +105,6 @@ int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter) precvpriv->signal_stat_sampling_interval = 1000; /* ms */ rtw_set_signal_stat_timer(precvpriv); -exit: - return res; } @@ -117,7 +113,6 @@ void _rtw_free_recv_priv(struct recv_priv *precvpriv) { struct adapter *padapter = precvpriv->adapter; - rtw_free_uc_swdec_pending_queue(padapter); if (precvpriv->pallocated_frame_buf) { @@ -153,7 +148,6 @@ struct recv_frame *_rtw_alloc_recvframe(struct __queue *pfree_recv_queue) } } - return (struct recv_frame *)hdr; } @@ -170,14 +164,6 @@ struct recv_frame *rtw_alloc_recvframe(struct __queue *pfree_recv_queue) return precvframe; } -void rtw_init_recvframe(struct recv_frame *precvframe, struct recv_priv *precvpriv) -{ - /* Perry: This can be removed */ - INIT_LIST_HEAD(&precvframe->list); - - precvframe->len = 0; -} - int rtw_free_recvframe(struct recv_frame *precvframe, struct __queue *pfree_recv_queue) { @@ -208,7 +194,6 @@ int rtw_free_recvframe(struct recv_frame *precvframe, spin_unlock_bh(&pfree_recv_queue->lock); - return _SUCCESS; } @@ -217,7 +202,6 @@ int _rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue) struct adapter *padapter = precvframe->adapter; struct recv_priv *precvpriv = &padapter->recvpriv; - list_del_init(&(precvframe->list)); list_add_tail(&(precvframe->list), get_list_head(queue)); @@ -226,7 +210,6 @@ int _rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue) precvpriv->free_recvframe_cnt++; } - return _SUCCESS; } @@ -421,7 +404,6 @@ static int recvframe_chkmic(struct adapter *adapter, exit: - return res; } @@ -483,7 +465,6 @@ static struct recv_frame *decryptor(struct adapter *padapter, return_packet = NULL; } - return return_packet; } @@ -502,7 +483,6 @@ static struct recv_frame *portctrl(struct adapter *adapter, struct rx_pkt_attrib *pattrib; __be16 be_tmp; - pstapriv = &adapter->stapriv; auth_alg = adapter->securitypriv.dot11AuthAlgrthm; @@ -561,7 +541,6 @@ static struct recv_frame *portctrl(struct adapter *adapter, prtnframe = precv_frame; } - return prtnframe; } @@ -573,7 +552,6 @@ static int recv_decache(struct recv_frame *precv_frame, u8 bretry, u16 seq_ctrl = ((precv_frame->attrib.seq_num&0xffff) << 4) | (precv_frame->attrib.frag_num & 0xf); - if (tid > 15) { RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("recv_decache, (tid>15)! seq_ctrl=0x%x, tid=0x%x\n", seq_ctrl, tid)); @@ -590,7 +568,6 @@ static int recv_decache(struct recv_frame *precv_frame, u8 bretry, prxcache->tid_rxseq[tid] = seq_ctrl; - return _SUCCESS; } @@ -727,7 +704,6 @@ int sta2sta_data_frame(struct adapter *adapter, struct recv_frame *precv_frame, u8 *sta_addr = NULL; int bmcast = IS_MCAST(pattrib->dst); - if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) || (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) { /* filter packets that SA is myself or multicast or broadcast */ @@ -815,7 +791,6 @@ static int ap2sta_data_frame( u8 *myhwaddr = myid(&adapter->eeprompriv); int bmcast = IS_MCAST(pattrib->dst); - if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) && (check_fwstate(pmlmepriv, _FW_LINKED) == true || check_fwstate(pmlmepriv, _FW_UNDER_LINKING))) { @@ -907,7 +882,6 @@ static int ap2sta_data_frame( exit: - return ret; } @@ -922,7 +896,6 @@ static int sta2ap_data_frame(struct adapter *adapter, unsigned char *mybssid = get_bssid(pmlmepriv); int ret = _SUCCESS; - if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) { /* For AP mode, RA = BSSID, TX = STA(SRC_ADDR), A3 = DST_ADDR */ if (memcmp(pattrib->bssid, mybssid, ETH_ALEN)) { @@ -967,7 +940,6 @@ static int sta2ap_data_frame(struct adapter *adapter, exit: - return ret; } @@ -1149,7 +1121,6 @@ static int validate_recv_data_frame(struct adapter *adapter, struct security_priv *psecuritypriv = &adapter->securitypriv; int ret = _SUCCESS; - bretry = GetRetry(ptr); pda = get_da(ptr); psa = get_sa(ptr); @@ -1253,7 +1224,6 @@ static int validate_recv_data_frame(struct adapter *adapter, exit: - return ret; } @@ -1273,7 +1243,6 @@ static int validate_recv_frame(struct adapter *adapter, u8 ver = (unsigned char)(*ptr)&0x3; struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { int ch_set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, rtw_get_oper_ch(adapter)); if (ch_set_idx >= 0) @@ -1362,7 +1331,6 @@ static int validate_recv_frame(struct adapter *adapter, exit: - return retval; } @@ -1445,7 +1413,6 @@ static struct recv_frame *recvframe_defrag(struct adapter *adapter, struct recv_frame *prframe, *pnextrframe; struct __queue *pfree_recv_queue; - curfragnum = 0; pfree_recv_queue = &adapter->recvpriv.free_recv_queue; @@ -1510,7 +1477,6 @@ static struct recv_frame *recvframe_defrag(struct adapter *adapter, RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("Performance defrag!!!!!\n")); - return prframe; } @@ -1528,7 +1494,6 @@ struct recv_frame *recvframe_chk_defrag(struct adapter *padapter, struct recv_frame *prtnframe = NULL; struct __queue *pfree_recv_queue, *pdefrag_q; - pstapriv = &padapter->stapriv; pfhdr = precv_frame; @@ -1612,7 +1577,6 @@ struct recv_frame *recvframe_chk_defrag(struct adapter *padapter, } } - return prtnframe; } @@ -2116,7 +2080,6 @@ s32 rtw_recv_entry(struct recv_frame *precvframe) struct recv_priv *precvpriv; s32 ret = _SUCCESS; - padapter = precvframe->adapter; precvpriv = &padapter->recvpriv; @@ -2129,7 +2092,6 @@ s32 rtw_recv_entry(struct recv_frame *precvframe) precvpriv->rx_pkts++; - return ret; _recv_entry_drop: diff --git a/drivers/staging/rtl8188eu/core/rtw_security.c b/drivers/staging/rtl8188eu/core/rtw_security.c index d870a5ce8585..22839d57dc8c 100644 --- a/drivers/staging/rtl8188eu/core/rtw_security.c +++ b/drivers/staging/rtl8188eu/core/rtw_security.c @@ -1330,7 +1330,7 @@ static int aes_decipher(u8 *key, uint hdrlen, bitwise_xor(aes_out, &pframe[payload_index], chain_buffer); for (j = 0; j < 16; j++) - pframe[payload_index++] = chain_buffer[j]; + pframe[payload_index++] = chain_buffer[j]; } if (payload_remainder > 0) { /* If there is a short final block, then pad it,*/ diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c index fda169d37771..5dc0b90e8ab5 100644 --- a/drivers/staging/rtl8188eu/core/rtw_xmit.c +++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c @@ -868,7 +868,7 @@ s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, struct pkt_attrib *pattr /* check if enable ampdu */ if (pattrib->ht_en && psta->htpriv.ampdu_enable) { if (psta->htpriv.agg_enable_bitmap & BIT(pattrib->priority)) - pattrib->ampdu_en = true; + pattrib->ampdu_en = true; } /* re-check if enable ampdu by BA_starting_seqctrl */ @@ -1026,22 +1026,22 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct /* adding icv, if necessary... */ if (pattrib->iv_len) { switch (pattrib->encrypt) { - case _WEP40_: - case _WEP104_: - WEP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx); - break; - case _TKIP_: - if (bmcst) - TKIP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx); - else - TKIP_IV(pattrib->iv, psta->dot11txpn, 0); - break; - case _AES_: - if (bmcst) - AES_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx); - else - AES_IV(pattrib->iv, psta->dot11txpn, 0); - break; + case _WEP40_: + case _WEP104_: + WEP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx); + break; + case _TKIP_: + if (bmcst) + TKIP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx); + else + TKIP_IV(pattrib->iv, psta->dot11txpn, 0); + break; + case _AES_: + if (bmcst) + AES_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx); + else + AES_IV(pattrib->iv, psta->dot11txpn, 0); + break; } memcpy(pframe, pattrib->iv, pattrib->iv_len); @@ -1769,7 +1769,7 @@ int xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct xmit_fra int bmcst = IS_MCAST(pattrib->ra); if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == false) - return ret; + return ret; if (pattrib->psta) psta = pattrib->psta; diff --git a/drivers/staging/rtl8188eu/hal/bb_cfg.c b/drivers/staging/rtl8188eu/hal/bb_cfg.c index 8eb2b39a0b67..9c7e626aa703 100644 --- a/drivers/staging/rtl8188eu/hal/bb_cfg.c +++ b/drivers/staging/rtl8188eu/hal/bb_cfg.c @@ -24,9 +24,9 @@ #define read_next_pair(array, v1, v2, i) \ do { \ - i += 2; \ - v1 = array[i]; \ - v2 = array[i+1]; \ + i += 2; \ + v1 = array[i]; \ + v2 = array[i+1]; \ } while (0) diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c index 28b5e7bd4fc0..710fdc3449f8 100644 --- a/drivers/staging/rtl8188eu/hal/odm.c +++ b/drivers/staging/rtl8188eu/hal/odm.c @@ -1170,13 +1170,10 @@ void odm_RSSIMonitorCheckCE(struct odm_dm_struct *pDM_Odm) } for (i = 0; i < sta_cnt; i++) { - if (PWDB_rssi[i] != (0)) { - if (pHalData->fw_ractrl) { - /* Report every sta's RSSI to FW */ - } else { - ODM_RA_SetRSSI_8188E( - &(pHalData->odmpriv), (PWDB_rssi[i]&0xFF), (u8)((PWDB_rssi[i]>>16) & 0xFF)); - } + if (PWDB_rssi[i] != 0) { + ODM_RA_SetRSSI_8188E(&pHalData->odmpriv, + PWDB_rssi[i] & 0xFF, + (PWDB_rssi[i] >> 16) & 0xFF); } } diff --git a/drivers/staging/rtl8188eu/hal/rf.c b/drivers/staging/rtl8188eu/hal/rf.c index 097092772a86..38845d17d593 100644 --- a/drivers/staging/rtl8188eu/hal/rf.c +++ b/drivers/staging/rtl8188eu/hal/rf.c @@ -102,7 +102,7 @@ void rtl88eu_phy_rf6052_set_cck_txpower(struct adapter *adapt, u8 *powerlevel) } } rtl88eu_dm_txpower_track_adjust(&hal_data->odmpriv, 1, &direction, - &pwrtrac_value); + &pwrtrac_value); if (direction == 1) { /* Increase TX power */ diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c index 86347f2ccdfd..0a62bfa210fe 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c @@ -127,27 +127,6 @@ exit: return ret; } -u8 rtl8188e_set_raid_cmd(struct adapter *adapt, u32 mask) -{ - u8 buf[3]; - u8 res = _SUCCESS; - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); - - if (haldata->fw_ractrl) { - - memset(buf, 0, 3); - put_unaligned_le32(mask, buf); - - FillH2CCmd_88E(adapt, H2C_DM_MACID_CFG, 3, buf); - } else { - DBG_88E("==>%s fw dont support RA\n", __func__); - res = _FAIL; - } - - - return res; -} - /* bitmap[0:27] = tx_rate_bitmap */ /* bitmap[28:31]= Rate Adaptive id */ /* arg[0:4] = macid */ diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 6dc0869924ec..1ef878fd997b 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -743,19 +743,16 @@ static u32 rtl8188eu_hal_init(struct adapter *Adapter) if (Adapter->registrypriv.mp_mode == 1) { _InitRxSetting(Adapter); Adapter->bFWReady = false; - haldata->fw_ractrl = false; } else { status = rtl88eu_download_fw(Adapter); if (status) { DBG_88E("%s: Download Firmware failed!!\n", __func__); Adapter->bFWReady = false; - haldata->fw_ractrl = false; return status; } else { RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("Initializeadapt8192CSdio(): Download Firmware Success!!\n")); Adapter->bFWReady = true; - haldata->fw_ractrl = false; } } rtl8188e_InitializeFirmwareVars(Adapter); @@ -2016,28 +2013,9 @@ static void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_l init_rate = get_highest_rate_idx(mask)&0x3f; - if (haldata->fw_ractrl) { - u8 arg; + ODM_RA_UpdateRateInfo_8188E(&haldata->odmpriv, mac_id, + raid, mask, shortGIrate); - arg = mac_id & 0x1f;/* MACID */ - arg |= BIT(7); - if (shortGIrate) - arg |= BIT(5); - mask |= ((raid << 28) & 0xf0000000); - DBG_88E("update raid entry, mask=0x%x, arg=0x%x\n", mask, arg); - psta->ra_mask = mask; - mask |= ((raid << 28) & 0xf0000000); - - /* to do ,for 8188E-SMIC */ - rtl8188e_set_raid_cmd(adapt, mask); - } else { - ODM_RA_UpdateRateInfo_8188E(&(haldata->odmpriv), - mac_id, - raid, - mask, - shortGIrate - ); - } /* set ra_id */ psta->raid = raid; psta->init_rate = init_rate; @@ -2087,7 +2065,6 @@ static void rtl8188eu_init_default_value(struct adapter *adapt) pwrctrlpriv = &adapt->pwrctrlpriv; /* init default value */ - haldata->fw_ractrl = false; if (!pwrctrlpriv->bkeepfwalive) haldata->LastHMEBoxNum = 0; diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index fabb95917e8b..6400f75707bd 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -477,53 +477,9 @@ struct ieee80211_snap_hdr { #define WLAN_GET_SEQ_FRAG(seq) ((seq) & RTW_IEEE80211_SCTL_FRAG) #define WLAN_GET_SEQ_SEQ(seq) ((seq) & RTW_IEEE80211_SCTL_SEQ) -/* Authentication algorithms */ -#define WLAN_AUTH_OPEN 0 -#define WLAN_AUTH_SHARED_KEY 1 - -#define WLAN_AUTH_CHALLENGE_LEN 128 - /* Non standard? Not in <linux/ieee80211.h> */ #define WLAN_REASON_EXPIRATION_CHK 65535 -/* Information Element IDs */ -#define WLAN_EID_SSID 0 -#define WLAN_EID_SUPP_RATES 1 -#define WLAN_EID_FH_PARAMS 2 -#define WLAN_EID_DS_PARAMS 3 -#define WLAN_EID_CF_PARAMS 4 -#define WLAN_EID_TIM 5 -#define WLAN_EID_IBSS_PARAMS 6 -#define WLAN_EID_CHALLENGE 16 -/* EIDs defined by IEEE 802.11h - START */ -#define WLAN_EID_PWR_CONSTRAINT 32 -#define WLAN_EID_PWR_CAPABILITY 33 -#define WLAN_EID_TPC_REQUEST 34 -#define WLAN_EID_TPC_REPORT 35 -#define WLAN_EID_SUPPORTED_CHANNELS 36 -#define WLAN_EID_CHANNEL_SWITCH 37 -#define WLAN_EID_MEASURE_REQUEST 38 -#define WLAN_EID_MEASURE_REPORT 39 -#define WLAN_EID_QUITE 40 -#define WLAN_EID_IBSS_DFS 41 -/* EIDs defined by IEEE 802.11h - END */ -#define WLAN_EID_ERP_INFO 42 -#define WLAN_EID_HT_CAP 45 -#define WLAN_EID_RSN 48 -#define WLAN_EID_EXT_SUPP_RATES 50 -#define WLAN_EID_MOBILITY_DOMAIN 54 -#define WLAN_EID_FAST_BSS_TRANSITION 55 -#define WLAN_EID_TIMEOUT_INTERVAL 56 -#define WLAN_EID_RIC_DATA 57 -#define WLAN_EID_HT_OPERATION 61 -#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62 -#define WLAN_EID_20_40_BSS_COEXISTENCE 72 -#define WLAN_EID_20_40_BSS_INTOLERANT 73 -#define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74 -#define WLAN_EID_MMIE 76 -#define WLAN_EID_VENDOR_SPECIFIC 221 -#define WLAN_EID_GENERIC (WLAN_EID_VENDOR_SPECIFIC) - #define IEEE80211_MGMT_HDR_LEN 24 #define IEEE80211_DATA_HDR3_LEN 24 #define IEEE80211_DATA_HDR4_LEN 30 diff --git a/drivers/staging/rtl8188eu/include/recv_osdep.h b/drivers/staging/rtl8188eu/include/recv_osdep.h index 0809963ce6aa..fdeb603b6cc1 100644 --- a/drivers/staging/rtl8188eu/include/recv_osdep.h +++ b/drivers/staging/rtl8188eu/include/recv_osdep.h @@ -38,8 +38,7 @@ void rtw_handle_tkip_mic_err(struct adapter *padapter, u8 bgroup); int rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter); void rtw_free_recv_priv(struct recv_priv *precvpriv); -int rtw_os_recv_resource_alloc(struct adapter *adapt, - struct recv_frame *recvfr); +void rtw_os_recv_resource_alloc(struct recv_frame *recvfr); int rtw_os_recvbuf_resource_alloc(struct adapter *adapt, struct recv_buf *buf); diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h b/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h index 42b1f22424eb..f813ce0563f8 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h @@ -107,7 +107,6 @@ struct P2P_PS_CTWPeriod_t { /* host message to firmware cmd */ void rtl8188e_set_FwPwrMode_cmd(struct adapter *padapter, u8 Mode); void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *padapter, u8 mstatus); -u8 rtl8188e_set_raid_cmd(struct adapter *padapter, u32 mask); void rtl8188e_Add_RateATid(struct adapter *padapter, u32 bitmap, u8 arg, u8 rssi_level); diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h index 5aa2adc1f013..cbad364f189c 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h @@ -294,7 +294,6 @@ struct hal_data_8188e { /* for host message to fw */ u8 LastHMEBoxNum; - u8 fw_ractrl; u8 RegTxPause; /* Beacon function related global variable. */ u32 RegBcnCtrlVal; diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme.h b/drivers/staging/rtl8188eu/include/rtw_mlme.h index 8c7e8a36aa13..4c992573e3ca 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme.h @@ -535,7 +535,8 @@ void rtw_generate_random_ibss(u8 *pibss); struct wlan_network *rtw_find_network(struct __queue *scanned_queue, u8 *addr); struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue); -void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue); +void rtw_free_assoc_resources(struct adapter *adapter); +void rtw_free_assoc_resources_locked(struct adapter *adapter); void rtw_indicate_disconnect(struct adapter *adapter); void rtw_indicate_connect(struct adapter *adapter); void rtw_indicate_scan_done(struct adapter *padapter, bool aborted); diff --git a/drivers/staging/rtl8188eu/include/sta_info.h b/drivers/staging/rtl8188eu/include/sta_info.h index 9612490539b3..7bbeedfc49aa 100644 --- a/drivers/staging/rtl8188eu/include/sta_info.h +++ b/drivers/staging/rtl8188eu/include/sta_info.h @@ -113,7 +113,6 @@ struct sta_info { u8 raid; u8 init_rate; - u32 ra_mask; u8 wireless_mode; /* NETWORK_TYPE */ struct stainfo_stats sta_stats; diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h index a08a2e045e59..dba8af1ec41e 100644 --- a/drivers/staging/rtl8188eu/include/wifi.h +++ b/drivers/staging/rtl8188eu/include/wifi.h @@ -649,13 +649,6 @@ enum ht_cap_ampdu_factor { #define IEEE80211_MAX_AMPDU_BUF 0x40 -/* Spatial Multiplexing Power Save Modes */ -#define WLAN_HT_CAP_SM_PS_STATIC 0 -#define WLAN_HT_CAP_SM_PS_DYNAMIC 1 -#define WLAN_HT_CAP_SM_PS_INVALID 2 -#define WLAN_HT_CAP_SM_PS_DISABLED 3 - - #define OP_MODE_PURE 0 #define OP_MODE_MAY_BE_LEGACY_STAS 1 #define OP_MODE_20MHZ_HT_STA_ASSOCED 2 diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c index ce756cdb817b..969574926e21 100644 --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c @@ -1871,7 +1871,7 @@ static int rtw_wx_set_auth(struct net_device *dev, rtw_disassoc_cmd(padapter, 500, false); DBG_88E("%s...call rtw_indicate_disconnect\n ", __func__); rtw_indicate_disconnect(padapter); - rtw_free_assoc_resources(padapter, 1); + rtw_free_assoc_resources(padapter); } ret = wpa_set_auth_algs(dev, (u32)param->value); break; @@ -2485,16 +2485,13 @@ static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int static int rtw_hostapd_sta_flush(struct net_device *dev) { - int ret = 0; struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); DBG_88E("%s\n", __func__); flush_all_cam_entry(padapter); /* clear CAM */ - ret = rtw_sta_flush(padapter); - - return ret; + return rtw_sta_flush(padapter); } static int rtw_add_sta(struct net_device *dev, struct ieee_param *param) @@ -2666,7 +2663,8 @@ static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param) psta = rtw_get_stainfo(pstapriv, param->sta_addr); if (psta) { - if ((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_GENERIC)) { + if (psta->wpa_ie[0] == WLAN_EID_RSN || + psta->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) { int wpa_ie_len; int copy_len; @@ -2809,7 +2807,6 @@ static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len) { - int ret = 0; struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); @@ -2820,13 +2817,11 @@ static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *p param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) return -EINVAL; - ret = rtw_acl_remove_sta(padapter, param->sta_addr); - return ret; + return rtw_acl_remove_sta(padapter, param->sta_addr); } static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len) { - int ret = 0; struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); @@ -2837,8 +2832,7 @@ static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *para param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) return -EINVAL; - ret = rtw_acl_add_sta(padapter, param->sta_addr); - return ret; + return rtw_acl_add_sta(padapter, param->sta_addr); } static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len) diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index a14e79f31abf..2361bce480c3 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -1175,7 +1175,7 @@ static int netdev_close(struct net_device *pnetdev) /* s2-2. indicate disconnect to os */ rtw_indicate_disconnect(padapter); /* s2-3. */ - rtw_free_assoc_resources(padapter, 1); + rtw_free_assoc_resources(padapter); /* s2-4. */ rtw_free_network_queue(padapter, true); /* Close LED */ diff --git a/drivers/staging/rtl8188eu/os_dep/recv_linux.c b/drivers/staging/rtl8188eu/os_dep/recv_linux.c index 05701328dce4..3ebb8b206e46 100644 --- a/drivers/staging/rtl8188eu/os_dep/recv_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/recv_linux.c @@ -17,8 +17,6 @@ * * ******************************************************************************/ -#define _RECV_OSDEP_C_ - #include <osdep_service.h> #include <drv_types.h> @@ -29,26 +27,22 @@ #include <usb_ops_linux.h> /* alloc os related resource in struct recv_frame */ -int rtw_os_recv_resource_alloc(struct adapter *padapter, - struct recv_frame *precvframe) +void rtw_os_recv_resource_alloc(struct recv_frame *precvframe) { precvframe->pkt_newalloc = NULL; precvframe->pkt = NULL; - return _SUCCESS; } /* alloc os related resource in struct recv_buf */ int rtw_os_recvbuf_resource_alloc(struct adapter *padapter, struct recv_buf *precvbuf) { - int res = _SUCCESS; - - precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL); - if (precvbuf->purb == NULL) - res = _FAIL; precvbuf->pskb = NULL; precvbuf->reuse = false; - return res; + precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL); + if (!precvbuf->purb) + return _FAIL; + return _SUCCESS; } void rtw_handle_tkip_mic_err(struct adapter *padapter, u8 bgroup) diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 5490b2905075..33bfe054f867 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -17,7 +17,6 @@ * * ******************************************************************************/ -#define _HCI_INTF_C_ #define pr_fmt(fmt) "R8188EU: " fmt #include <osdep_service.h> @@ -64,10 +63,9 @@ static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf) struct usb_endpoint_descriptor *pendp_desc; struct usb_device *pusbd; - pdvobjpriv = kzalloc(sizeof(*pdvobjpriv), GFP_KERNEL); if (pdvobjpriv == NULL) - goto exit; + return NULL; pdvobjpriv->pusbintf = usb_intf; pusbd = interface_to_usbdev(usb_intf); @@ -115,14 +113,13 @@ static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf) mutex_init(&pdvobjpriv->usb_vendor_req_mutex); pdvobjpriv->usb_vendor_req_buf = kzalloc(MAX_USB_IO_CTL_SIZE, GFP_KERNEL); - if (pdvobjpriv->usb_vendor_req_buf) { - usb_get_dev(pusbd); - } else { + if (!pdvobjpriv->usb_vendor_req_buf) { usb_set_intfdata(usb_intf, NULL); kfree(pdvobjpriv); - pdvobjpriv = NULL; + return NULL; } -exit: + usb_get_dev(pusbd); + return pdvobjpriv; } @@ -130,7 +127,6 @@ static void usb_dvobj_deinit(struct usb_interface *usb_intf) { struct dvobj_priv *dvobj = usb_get_intfdata(usb_intf); - usb_set_intfdata(usb_intf, NULL); if (dvobj) { /* Modify condition for 92DU DMDP 2010.11.18, by Thomas */ @@ -270,7 +266,7 @@ static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message) /* s2-2. indicate disconnect to os */ rtw_indicate_disconnect(padapter); /* s2-3. */ - rtw_free_assoc_resources(padapter, 1); + rtw_free_assoc_resources(padapter); /* s2-4. */ rtw_free_network_queue(padapter, true); @@ -328,7 +324,6 @@ exit: pr_debug("<=== %s return %d.............. in %dms\n", __func__, ret, rtw_get_passing_time_ms(start_time)); - return ret; } @@ -476,7 +471,6 @@ static void rtw_usb_if1_deinit(struct adapter *if1) static int rtw_drv_init(struct usb_interface *pusb_intf, const struct usb_device_id *pdid) { struct adapter *if1 = NULL; - int status = _FAIL; struct dvobj_priv *dvobj; RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_init\n")); @@ -497,13 +491,12 @@ static int rtw_drv_init(struct usb_interface *pusb_intf, const struct usb_device RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-871x_drv - drv_init, success!\n")); - status = _SUCCESS; + return 0; free_dvobj: - if (status != _SUCCESS) - usb_dvobj_deinit(pusb_intf); + usb_dvobj_deinit(pusb_intf); exit: - return status == _SUCCESS ? 0 : -ENODEV; + return -ENODEV; } /* @@ -515,7 +508,6 @@ static void rtw_dev_remove(struct usb_interface *pusb_intf) struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf); struct adapter *padapter = dvobj->if1; - pr_debug("+rtw_dev_remove\n"); RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+dev_remove()\n")); diff --git a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c index f3eb1dc3da73..c8f25ade2535 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c @@ -22,55 +22,38 @@ #include "r8192E_phy.h" #include "r8190P_rtl8256.h" -void PHY_SetRF8256Bandwidth(struct net_device *dev, - enum ht_channel_width Bandwidth) +void rtl92e_set_bandwidth(struct net_device *dev, + enum ht_channel_width Bandwidth) { u8 eRFPath; struct r8192_priv *priv = rtllib_priv(dev); + if (priv->card_8192_version != VERSION_8190_BD && + priv->card_8192_version != VERSION_8190_BE) { + netdev_warn(dev, "%s(): Unknown HW version.\n", __func__); + return; + } + for (eRFPath = 0; eRFPath < priv->NumTotalRFPath; eRFPath++) { - if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath)) + if (!rtl92e_is_legal_rf_path(dev, eRFPath)) continue; switch (Bandwidth) { case HT_CHANNEL_WIDTH_20: - if (priv->card_8192_version == VERSION_8190_BD || - priv->card_8192_version == VERSION_8190_BE) { - rtl8192_phy_SetRFReg(dev, - (enum rf90_radio_path)eRFPath, - 0x0b, bMask12Bits, 0x100); - rtl8192_phy_SetRFReg(dev, - (enum rf90_radio_path)eRFPath, - 0x2c, bMask12Bits, 0x3d7); - rtl8192_phy_SetRFReg(dev, - (enum rf90_radio_path)eRFPath, - 0x0e, bMask12Bits, 0x021); - - } else { - netdev_warn(dev, "%s(): Unknown HW version.\n", - __func__); - } - + rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath, + 0x0b, bMask12Bits, 0x100); + rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath, + 0x2c, bMask12Bits, 0x3d7); + rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath, + 0x0e, bMask12Bits, 0x021); break; case HT_CHANNEL_WIDTH_20_40: - if (priv->card_8192_version == VERSION_8190_BD || - priv->card_8192_version == VERSION_8190_BE) { - rtl8192_phy_SetRFReg(dev, - (enum rf90_radio_path)eRFPath, - 0x0b, bMask12Bits, 0x300); - rtl8192_phy_SetRFReg(dev, - (enum rf90_radio_path)eRFPath, - 0x2c, bMask12Bits, 0x3ff); - rtl8192_phy_SetRFReg(dev, - (enum rf90_radio_path)eRFPath, - 0x0e, bMask12Bits, 0x0e1); - - } else { - netdev_warn(dev, "%s(): Unknown HW version.\n", - __func__); - } - - + rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath, + 0x0b, bMask12Bits, 0x300); + rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath, + 0x2c, bMask12Bits, 0x3ff); + rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath, + 0x0e, bMask12Bits, 0x0e1); break; default: netdev_err(dev, "%s(): Unknown bandwidth: %#X\n", @@ -81,7 +64,7 @@ void PHY_SetRF8256Bandwidth(struct net_device *dev, } } -static bool phy_RF8256_Config_ParaFile(struct net_device *dev) +bool rtl92e_config_rf(struct net_device *dev) { u32 u4RegValue = 0; u8 eRFPath; @@ -94,9 +77,11 @@ static bool phy_RF8256_Config_ParaFile(struct net_device *dev) u8 ConstRetryTimes = 5, RetryTimes = 5; u8 ret = 0; + priv->NumTotalRFPath = RTL819X_TOTAL_RF_PATH; + for (eRFPath = (enum rf90_radio_path)RF90_PATH_A; eRFPath < priv->NumTotalRFPath; eRFPath++) { - if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath)) + if (!rtl92e_is_legal_rf_path(dev, eRFPath)) continue; pPhyReg = &priv->PHYRegDef[eRFPath]; @@ -105,114 +90,63 @@ static bool phy_RF8256_Config_ParaFile(struct net_device *dev) switch (eRFPath) { case RF90_PATH_A: case RF90_PATH_C: - u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, - bRFSI_RFENV); + u4RegValue = rtl92e_get_bb_reg(dev, pPhyReg->rfintfs, + bRFSI_RFENV); break; case RF90_PATH_B: case RF90_PATH_D: - u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, - bRFSI_RFENV<<16); + u4RegValue = rtl92e_get_bb_reg(dev, pPhyReg->rfintfs, + bRFSI_RFENV<<16); break; } - rtl8192_setBBreg(dev, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1); + rtl92e_set_bb_reg(dev, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1); - rtl8192_setBBreg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0x1); + rtl92e_set_bb_reg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0x1); - rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, - b3WireAddressLength, 0x0); - rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, - b3WireDataLength, 0x0); + rtl92e_set_bb_reg(dev, pPhyReg->rfHSSIPara2, + b3WireAddressLength, 0x0); + rtl92e_set_bb_reg(dev, pPhyReg->rfHSSIPara2, + b3WireDataLength, 0x0); - rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path) eRFPath, 0x0, - bMask12Bits, 0xbf); + rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath, 0x0, + bMask12Bits, 0xbf); - rtStatus = rtl8192_phy_checkBBAndRF(dev, HW90_BLOCK_RF, - (enum rf90_radio_path)eRFPath); + rtStatus = rtl92e_check_bb_and_rf(dev, HW90_BLOCK_RF, + (enum rf90_radio_path)eRFPath); if (!rtStatus) { netdev_err(dev, "%s(): Failed to check RF Path %d.\n", __func__, eRFPath); - goto phy_RF8256_Config_ParaFile_Fail; + goto fail; } RetryTimes = ConstRetryTimes; RF3_Final_Value = 0; - switch (eRFPath) { - case RF90_PATH_A: - while (RF3_Final_Value != RegValueToBeCheck && - RetryTimes != 0) { - ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, + while (RF3_Final_Value != RegValueToBeCheck && + RetryTimes != 0) { + ret = rtl92e_config_rf_path(dev, (enum rf90_radio_path)eRFPath); - RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, - (enum rf90_radio_path)eRFPath, - RegOffSetToBeCheck, - bMask12Bits); - RT_TRACE(COMP_RF, - "RF %d %d register final value: %x\n", - eRFPath, RegOffSetToBeCheck, - RF3_Final_Value); - RetryTimes--; - } - break; - case RF90_PATH_B: - while (RF3_Final_Value != RegValueToBeCheck && - RetryTimes != 0) { - ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, - (enum rf90_radio_path)eRFPath); - RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, - (enum rf90_radio_path)eRFPath, - RegOffSetToBeCheck, - bMask12Bits); - RT_TRACE(COMP_RF, - "RF %d %d register final value: %x\n", - eRFPath, RegOffSetToBeCheck, - RF3_Final_Value); - RetryTimes--; - } - break; - case RF90_PATH_C: - while (RF3_Final_Value != RegValueToBeCheck && - RetryTimes != 0) { - ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, - (enum rf90_radio_path)eRFPath); - RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, + RF3_Final_Value = rtl92e_get_rf_reg(dev, (enum rf90_radio_path)eRFPath, RegOffSetToBeCheck, bMask12Bits); - RT_TRACE(COMP_RF, - "RF %d %d register final value: %x\n", - eRFPath, RegOffSetToBeCheck, - RF3_Final_Value); - RetryTimes--; - } - break; - case RF90_PATH_D: - while (RF3_Final_Value != RegValueToBeCheck && - RetryTimes != 0) { - ret = rtl8192_phy_ConfigRFWithHeaderFile(dev, - (enum rf90_radio_path)eRFPath); - RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, - (enum rf90_radio_path)eRFPath, - RegOffSetToBeCheck, bMask12Bits); - RT_TRACE(COMP_RF, - "RF %d %d register final value: %x\n", - eRFPath, RegOffSetToBeCheck, - RF3_Final_Value); - RetryTimes--; - } - break; + RT_TRACE(COMP_RF, + "RF %d %d register final value: %x\n", + eRFPath, RegOffSetToBeCheck, + RF3_Final_Value); + RetryTimes--; } switch (eRFPath) { case RF90_PATH_A: case RF90_PATH_C: - rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV, - u4RegValue); + rtl92e_set_bb_reg(dev, pPhyReg->rfintfs, bRFSI_RFENV, + u4RegValue); break; case RF90_PATH_B: case RF90_PATH_D: - rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16, - u4RegValue); + rtl92e_set_bb_reg(dev, pPhyReg->rfintfs, + bRFSI_RFENV<<16, u4RegValue); break; } @@ -220,7 +154,7 @@ static bool phy_RF8256_Config_ParaFile(struct net_device *dev) netdev_err(dev, "%s(): Failed to initialize RF Path %d.\n", __func__, eRFPath); - goto phy_RF8256_Config_ParaFile_Fail; + goto fail; } } @@ -228,19 +162,11 @@ static bool phy_RF8256_Config_ParaFile(struct net_device *dev) RT_TRACE(COMP_PHY, "PHY Initialization Success\n"); return true; -phy_RF8256_Config_ParaFile_Fail: +fail: return false; } -bool PHY_RF8256_Config(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - priv->NumTotalRFPath = RTL819X_TOTAL_RF_PATH; - return phy_RF8256_Config_ParaFile(dev); -} - -void PHY_SetRF8256CCKTxPower(struct net_device *dev, u8 powerlevel) +void rtl92e_set_cck_tx_power(struct net_device *dev, u8 powerlevel) { u32 TxAGC = 0; struct r8192_priv *priv = rtllib_priv(dev); @@ -254,11 +180,11 @@ void PHY_SetRF8256CCKTxPower(struct net_device *dev, u8 powerlevel) } if (TxAGC > 0x24) TxAGC = 0x24; - rtl8192_setBBreg(dev, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC); + rtl92e_set_bb_reg(dev, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC); } -void PHY_SetRF8256OFDMTxPower(struct net_device *dev, u8 powerlevel) +void rtl92e_set_ofdm_tx_power(struct net_device *dev, u8 powerlevel) { struct r8192_priv *priv = rtllib_priv(dev); u32 writeVal, powerBase0, powerBase1, writeVal_tmp; @@ -300,7 +226,7 @@ void PHY_SetRF8256OFDMTxPower(struct net_device *dev, u8 powerlevel) else writeVal = (byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0; - rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal); + rtl92e_set_bb_reg(dev, RegOffset[index], 0x7f7f7f7f, writeVal); } } diff --git a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.h b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.h index d9348d92af26..5af837f969b8 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.h +++ b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.h @@ -21,10 +21,10 @@ #define RTL8225H #define RTL819X_TOTAL_RF_PATH 2 -extern void PHY_SetRF8256Bandwidth(struct net_device *dev, - enum ht_channel_width Bandwidth); -extern bool PHY_RF8256_Config(struct net_device *dev); -extern void PHY_SetRF8256CCKTxPower(struct net_device *dev, u8 powerlevel); -extern void PHY_SetRF8256OFDMTxPower(struct net_device *dev, u8 powerlevel); +extern void rtl92e_set_bandwidth(struct net_device *dev, + enum ht_channel_width Bandwidth); +extern bool rtl92e_config_rf(struct net_device *dev); +extern void rtl92e_set_cck_tx_power(struct net_device *dev, u8 powerlevel); +extern void rtl92e_set_ofdm_tx_power(struct net_device *dev, u8 powerlevel); #endif diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c index ebd08a16685e..9ddabf59784c 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c @@ -21,11 +21,8 @@ #include "r8192E_hw.h" #include "r8192E_cmdpkt.h" -bool cmpk_message_handle_tx( - struct net_device *dev, - u8 *code_virtual_address, - u32 packettype, - u32 buffer_len) +bool rtl92e_send_cmd_pkt(struct net_device *dev, u8 *code_virtual_address, + u32 packettype, u32 buffer_len) { bool rt_status = true; @@ -41,7 +38,7 @@ bool cmpk_message_handle_tx( struct tx_fwinfo_8190pci *pTxFwInfo = NULL; RT_TRACE(COMP_CMDPKT, "%s(),buffer_len is %d\n", __func__, buffer_len); - firmware_init_param(dev); + rtl92e_init_fw_param(dev); frag_threshold = pfirmware->cmdpacket_frag_thresold; do { @@ -84,7 +81,7 @@ bool cmpk_message_handle_tx( } while (frag_offset < buffer_len); - write_nic_byte(dev, TPPoll, TPPoll_CQ); + rtl92e_writeb(dev, TPPoll, TPPoll_CQ); Failed: return rt_status; } diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h index f714d5100059..5718fd8fd118 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h @@ -19,7 +19,6 @@ #ifndef R819XUSB_CMDPKT_H #define R819XUSB_CMDPKT_H -extern bool cmpk_message_handle_tx(struct net_device *dev, - u8 *codevirtualaddress, u32 packettype, - u32 buffer_len); +extern bool rtl92e_send_cmd_pkt(struct net_device *dev, u8 *codevirtualaddress, + u32 packettype, u32 buffer_len); #endif diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c index eb919b634e3c..c28cabc23fc0 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c @@ -33,7 +33,7 @@ static int WDCAPARA_ADD[] = {EDCAPARA_BE, EDCAPARA_BK, EDCAPARA_VI, EDCAPARA_VO}; -void rtl8192e_start_beacon(struct net_device *dev) +void rtl92e_start_beacon(struct net_device *dev) { struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); struct rtllib_network *net = &priv->rtllib->current_network; @@ -41,20 +41,20 @@ void rtl8192e_start_beacon(struct net_device *dev) u16 BcnCW = 6; u16 BcnIFS = 0xf; - rtl8192_irq_disable(dev); + rtl92e_irq_disable(dev); - write_nic_word(dev, ATIMWND, 2); + rtl92e_writew(dev, ATIMWND, 2); - write_nic_word(dev, BCN_INTERVAL, net->beacon_interval); - write_nic_word(dev, BCN_DRV_EARLY_INT, 10); - write_nic_word(dev, BCN_DMATIME, 256); + rtl92e_writew(dev, BCN_INTERVAL, net->beacon_interval); + rtl92e_writew(dev, BCN_DRV_EARLY_INT, 10); + rtl92e_writew(dev, BCN_DMATIME, 256); - write_nic_byte(dev, BCN_ERR_THRESH, 100); + rtl92e_writeb(dev, BCN_ERR_THRESH, 100); BcnTimeCfg |= BcnCW<<BCN_TCFG_CW_SHIFT; BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS; - write_nic_word(dev, BCN_TCFG, BcnTimeCfg); - rtl8192_irq_enable(dev); + rtl92e_writew(dev, BCN_TCFG, BcnTimeCfg); + rtl92e_irq_enable(dev); } static void rtl8192e_update_msr(struct net_device *dev) @@ -63,7 +63,7 @@ static void rtl8192e_update_msr(struct net_device *dev) u8 msr; enum led_ctl_mode LedAction = LED_CTL_NO_LINK; - msr = read_nic_byte(dev, MSR); + msr = rtl92e_readb(dev, MSR); msr &= ~MSR_LINK_MASK; switch (priv->rtllib->iw_mode) { @@ -90,26 +90,26 @@ static void rtl8192e_update_msr(struct net_device *dev) break; } - write_nic_byte(dev, MSR, msr); + rtl92e_writeb(dev, MSR, msr); if (priv->rtllib->LedControlHandler) priv->rtllib->LedControlHandler(dev, LedAction); } -void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val) +void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val) { struct r8192_priv *priv = rtllib_priv(dev); switch (variable) { case HW_VAR_BSSID: - write_nic_dword(dev, BSSIDR, ((u32 *)(val))[0]); - write_nic_word(dev, BSSIDR+2, ((u16 *)(val+2))[0]); + rtl92e_writel(dev, BSSIDR, ((u32 *)(val))[0]); + rtl92e_writew(dev, BSSIDR+2, ((u16 *)(val+2))[0]); break; case HW_VAR_MEDIA_STATUS: { enum rt_op_mode OpMode = *((enum rt_op_mode *)(val)); enum led_ctl_mode LedAction = LED_CTL_NO_LINK; - u8 btMsr = read_nic_byte(dev, MSR); + u8 btMsr = rtl92e_readb(dev, MSR); btMsr &= 0xfc; @@ -133,7 +133,7 @@ void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val) break; } - write_nic_byte(dev, MSR, btMsr); + rtl92e_writeb(dev, MSR, btMsr); } break; @@ -143,7 +143,7 @@ void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val) u32 RegRCR, Type; Type = ((u8 *)(val))[0]; - RegRCR = read_nic_dword(dev, RCR); + RegRCR = rtl92e_readl(dev, RCR); priv->ReceiveConfig = RegRCR; if (Type == true) @@ -151,7 +151,7 @@ void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val) else if (Type == false) RegRCR &= (~RCR_CBSSID); - write_nic_dword(dev, RCR, RegRCR); + rtl92e_writel(dev, RCR, RegRCR); priv->ReceiveConfig = RegRCR; } @@ -160,7 +160,7 @@ void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val) case HW_VAR_SLOT_TIME: priv->slot_time = val[0]; - write_nic_byte(dev, SLOT_TIME, val[0]); + rtl92e_writeb(dev, SLOT_TIME, val[0]); break; @@ -172,12 +172,12 @@ void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val) regTmp = priv->basic_rate; if (priv->short_preamble) regTmp |= BRSR_AckShortPmb; - write_nic_dword(dev, RRSR, regTmp); + rtl92e_writel(dev, RRSR, regTmp); break; } case HW_VAR_CPU_RST: - write_nic_dword(dev, CPU_GEN, ((u32 *)(val))[0]); + rtl92e_writel(dev, CPU_GEN, ((u32 *)(val))[0]); break; case HW_VAR_AC_PARAM: @@ -193,7 +193,7 @@ void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val) u1bAIFS = qop->aifs[pAcParam] * ((mode&(IEEE_G|IEEE_N_24G)) ? 9 : 20) + aSifsTime; - dm_init_edca_turbo(dev); + rtl92e_dm_init_edca_turbo(dev); u4bAcParam = (le16_to_cpu(qop->tx_op_limit[pAcParam]) << AC_PARAM_TXOP_LIMIT_OFFSET) | @@ -207,19 +207,19 @@ void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val) __func__, eACI, u4bAcParam); switch (eACI) { case AC1_BK: - write_nic_dword(dev, EDCAPARA_BK, u4bAcParam); + rtl92e_writel(dev, EDCAPARA_BK, u4bAcParam); break; case AC0_BE: - write_nic_dword(dev, EDCAPARA_BE, u4bAcParam); + rtl92e_writel(dev, EDCAPARA_BE, u4bAcParam); break; case AC2_VI: - write_nic_dword(dev, EDCAPARA_VI, u4bAcParam); + rtl92e_writel(dev, EDCAPARA_VI, u4bAcParam); break; case AC3_VO: - write_nic_dword(dev, EDCAPARA_VO, u4bAcParam); + rtl92e_writel(dev, EDCAPARA_VO, u4bAcParam); break; default: @@ -241,7 +241,7 @@ void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val) union aci_aifsn *pAciAifsn = (union aci_aifsn *) & (qos_parameters->aifs[0]); u8 acm = pAciAifsn->f.acm; - u8 AcmCtrl = read_nic_byte(dev, AcmHwCtrl); + u8 AcmCtrl = rtl92e_readb(dev, AcmHwCtrl); RT_TRACE(COMP_DBG, "===========>%s():HW_VAR_ACM_CTRL:%x\n", __func__, eACI); @@ -289,20 +289,20 @@ void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val) RT_TRACE(COMP_QOS, "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl); - write_nic_byte(dev, AcmHwCtrl, AcmCtrl); + rtl92e_writeb(dev, AcmHwCtrl, AcmCtrl); break; } case HW_VAR_SIFS: - write_nic_byte(dev, SIFS, val[0]); - write_nic_byte(dev, SIFS+1, val[0]); + rtl92e_writeb(dev, SIFS, val[0]); + rtl92e_writeb(dev, SIFS+1, val[0]); break; case HW_VAR_RF_TIMING: { u8 Rf_Timing = *((u8 *)val); - write_nic_byte(dev, rFPGA0_RFTiming1, Rf_Timing); + rtl92e_writeb(dev, rFPGA0_RFTiming1, Rf_Timing); break; } @@ -323,7 +323,7 @@ static void rtl8192_read_eeprom_info(struct net_device *dev) RT_TRACE(COMP_INIT, "====> rtl8192_read_eeprom_info\n"); - EEPROMId = eprom_read(dev, 0); + EEPROMId = rtl92e_eeprom_read(dev, 0); if (EEPROMId != RTL8190_EEPROM_ID) { netdev_err(dev, "%s(): Invalid EEPROM ID: %x\n", __func__, EEPROMId); @@ -333,12 +333,14 @@ static void rtl8192_read_eeprom_info(struct net_device *dev) } if (!priv->AutoloadFailFlag) { - priv->eeprom_vid = eprom_read(dev, EEPROM_VID >> 1); - priv->eeprom_did = eprom_read(dev, EEPROM_DID >> 1); + priv->eeprom_vid = rtl92e_eeprom_read(dev, EEPROM_VID >> 1); + priv->eeprom_did = rtl92e_eeprom_read(dev, EEPROM_DID >> 1); - usValue = eprom_read(dev, (u16)(EEPROM_Customer_ID>>1)) >> 8; + usValue = rtl92e_eeprom_read(dev, + (u16)(EEPROM_Customer_ID>>1)) >> 8; priv->eeprom_CustomerID = (u8)(usValue & 0xff); - usValue = eprom_read(dev, EEPROM_ICVersion_ChannelPlan>>1); + usValue = rtl92e_eeprom_read(dev, + EEPROM_ICVersion_ChannelPlan>>1); priv->eeprom_ChannelPlan = usValue&0xff; IC_Version = (usValue & 0xff00)>>8; @@ -376,7 +378,7 @@ static void rtl8192_read_eeprom_info(struct net_device *dev) if (!priv->AutoloadFailFlag) { for (i = 0; i < 6; i += 2) { - usValue = eprom_read(dev, + usValue = rtl92e_eeprom_read(dev, (u16)((EEPROM_NODE_ADDRESS_BYTE_0 + i) >> 1)); *(u16 *)(&dev->dev_addr[i]) = usValue; } @@ -396,8 +398,8 @@ static void rtl8192_read_eeprom_info(struct net_device *dev) if (priv->card_8192_version > VERSION_8190_BD) { if (!priv->AutoloadFailFlag) { - tempval = (eprom_read(dev, (EEPROM_RFInd_PowerDiff >> - 1))) & 0xff; + tempval = (rtl92e_eeprom_read(dev, + (EEPROM_RFInd_PowerDiff >> 1))) & 0xff; priv->EEPROMLegacyHTTxPowerDiff = tempval & 0xf; if (tempval&0x80) @@ -411,7 +413,7 @@ static void rtl8192_read_eeprom_info(struct net_device *dev) priv->EEPROMLegacyHTTxPowerDiff); if (!priv->AutoloadFailFlag) - priv->EEPROMThermalMeter = (u8)(((eprom_read(dev, + priv->EEPROMThermalMeter = (u8)(((rtl92e_eeprom_read(dev, (EEPROM_ThermalMeter>>1))) & 0xff00)>>8); else @@ -422,7 +424,7 @@ static void rtl8192_read_eeprom_info(struct net_device *dev) if (priv->epromtype == EEPROM_93C46) { if (!priv->AutoloadFailFlag) { - usValue = eprom_read(dev, + usValue = rtl92e_eeprom_read(dev, EEPROM_TxPwDiff_CrystalCap >> 1); priv->EEPROMAntPwDiff = (usValue&0x0fff); priv->EEPROMCrystalCap = (u8)((usValue & 0xf000) @@ -440,7 +442,7 @@ static void rtl8192_read_eeprom_info(struct net_device *dev) for (i = 0; i < 14; i += 2) { if (!priv->AutoloadFailFlag) - usValue = eprom_read(dev, + usValue = rtl92e_eeprom_read(dev, (u16)((EEPROM_TxPwIndex_CCK + i) >> 1)); else @@ -456,7 +458,7 @@ static void rtl8192_read_eeprom_info(struct net_device *dev) } for (i = 0; i < 14; i += 2) { if (!priv->AutoloadFailFlag) - usValue = eprom_read(dev, + usValue = rtl92e_eeprom_read(dev, (u16)((EEPROM_TxPwIndex_OFDM_24G + i) >> 1)); else @@ -560,7 +562,7 @@ static void rtl8192_read_eeprom_info(struct net_device *dev) RT_TRACE(COMP_INIT, "\n2T4R config\n"); } - init_rate_adaptive(dev); + rtl92e_init_adaptive_rate(dev); priv->rf_chip = RF_8256; @@ -625,13 +627,13 @@ static void rtl8192_read_eeprom_info(struct net_device *dev) RT_TRACE(COMP_TRACE, "<==== ReadAdapterInfo\n"); } -void rtl8192_get_eeprom_size(struct net_device *dev) +void rtl92e_get_eeprom_size(struct net_device *dev) { u16 curCR; struct r8192_priv *priv = rtllib_priv(dev); RT_TRACE(COMP_INIT, "===========>%s()\n", __func__); - curCR = read_nic_dword(dev, EPROM_CMD); + curCR = rtl92e_readl(dev, EPROM_CMD); RT_TRACE(COMP_INIT, "read from Reg Cmd9346CR(%x):%x\n", EPROM_CMD, curCR); priv->epromtype = (curCR & EPROM_CMD_9356SEL) ? EEPROM_93C56 : @@ -683,26 +685,26 @@ static void rtl8192_hwconfig(struct net_device *dev) break; } - write_nic_byte(dev, BW_OPMODE, regBwOpMode); + rtl92e_writeb(dev, BW_OPMODE, regBwOpMode); { u32 ratr_value = 0; ratr_value = regRATR; if (priv->rf_type == RF_1T2R) ratr_value &= ~(RATE_ALL_OFDM_2SS); - write_nic_dword(dev, RATR0, ratr_value); - write_nic_byte(dev, UFWP, 1); + rtl92e_writel(dev, RATR0, ratr_value); + rtl92e_writeb(dev, UFWP, 1); } - regTmp = read_nic_byte(dev, 0x313); + regTmp = rtl92e_readb(dev, 0x313); regRRSR = ((regTmp) << 24) | (regRRSR & 0x00ffffff); - write_nic_dword(dev, RRSR, regRRSR); + rtl92e_writel(dev, RRSR, regRRSR); - write_nic_word(dev, RETRY_LIMIT, - priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT | - priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT); + rtl92e_writew(dev, RETRY_LIMIT, + priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT | + priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT); } -bool rtl8192_adapter_start(struct net_device *dev) +bool rtl92e_start_adapter(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); u32 ulRegRead; @@ -718,10 +720,10 @@ bool rtl8192_adapter_start(struct net_device *dev) priv->being_init_adapter = true; start: - rtl8192_pci_resetdescring(dev); + rtl92e_reset_desc_ring(dev); priv->Rf_Mode = RF_OP_By_SW_3wire; if (priv->ResetProgress == RESET_TYPE_NORESET) { - write_nic_byte(dev, ANAPAR, 0x37); + rtl92e_writeb(dev, ANAPAR, 0x37); mdelay(500); } priv->pFirmware->firmware_status = FW_STATUS_0_INIT; @@ -729,7 +731,7 @@ start: if (priv->RegRfOff) priv->rtllib->eRFPowerState = eRfOff; - ulRegRead = read_nic_dword(dev, CPU_GEN); + ulRegRead = rtl92e_readl(dev, CPU_GEN); if (priv->pFirmware->firmware_status == FW_STATUS_0_INIT) ulRegRead |= CPU_GEN_SYSTEM_RESET; else if (priv->pFirmware->firmware_status == FW_STATUS_5_READY) @@ -738,19 +740,19 @@ start: netdev_err(dev, "%s(): undefined firmware state: %d.\n", __func__, priv->pFirmware->firmware_status); - write_nic_dword(dev, CPU_GEN, ulRegRead); + rtl92e_writel(dev, CPU_GEN, ulRegRead); - ICVersion = read_nic_byte(dev, IC_VERRSION); + ICVersion = rtl92e_readb(dev, IC_VERRSION); if (ICVersion >= 0x4) { - SwitchingRegulatorOutput = read_nic_byte(dev, SWREGULATOR); + SwitchingRegulatorOutput = rtl92e_readb(dev, SWREGULATOR); if (SwitchingRegulatorOutput != 0xb8) { - write_nic_byte(dev, SWREGULATOR, 0xa8); + rtl92e_writeb(dev, SWREGULATOR, 0xa8); mdelay(1); - write_nic_byte(dev, SWREGULATOR, 0xb8); + rtl92e_writeb(dev, SWREGULATOR, 0xb8); } } RT_TRACE(COMP_INIT, "BB Config Start!\n"); - rtStatus = rtl8192_BBConfig(dev); + rtStatus = rtl92e_config_bb(dev); if (!rtStatus) { netdev_warn(dev, "%s(): Failed to configure BB\n", __func__); return rtStatus; @@ -759,7 +761,7 @@ start: priv->LoopbackMode = RTL819X_NO_LOOPBACK; if (priv->ResetProgress == RESET_TYPE_NORESET) { - ulRegRead = read_nic_dword(dev, CPU_GEN); + ulRegRead = rtl92e_readl(dev, CPU_GEN); if (priv->LoopbackMode == RTL819X_NO_LOOPBACK) ulRegRead = ((ulRegRead & CPU_GEN_NO_LOOPBACK_MSK) | CPU_GEN_NO_LOOPBACK_SET); @@ -769,73 +771,73 @@ start: netdev_err(dev, "%s: Invalid loopback mode setting.\n", __func__); - write_nic_dword(dev, CPU_GEN, ulRegRead); + rtl92e_writel(dev, CPU_GEN, ulRegRead); udelay(500); } rtl8192_hwconfig(dev); - write_nic_byte(dev, CMDR, CR_RE | CR_TE); - - write_nic_byte(dev, PCIF, ((MXDMA2_NoLimit<<MXDMA2_RX_SHIFT) | - (MXDMA2_NoLimit<<MXDMA2_TX_SHIFT))); - write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]); - write_nic_word(dev, MAC4, ((u16 *)(dev->dev_addr + 4))[0]); - write_nic_dword(dev, RCR, priv->ReceiveConfig); - - write_nic_dword(dev, RQPN1, NUM_OF_PAGE_IN_FW_QUEUE_BK << - RSVD_FW_QUEUE_PAGE_BK_SHIFT | - NUM_OF_PAGE_IN_FW_QUEUE_BE << - RSVD_FW_QUEUE_PAGE_BE_SHIFT | - NUM_OF_PAGE_IN_FW_QUEUE_VI << - RSVD_FW_QUEUE_PAGE_VI_SHIFT | - NUM_OF_PAGE_IN_FW_QUEUE_VO << - RSVD_FW_QUEUE_PAGE_VO_SHIFT); - write_nic_dword(dev, RQPN2, NUM_OF_PAGE_IN_FW_QUEUE_MGNT << - RSVD_FW_QUEUE_PAGE_MGNT_SHIFT); - write_nic_dword(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW | - NUM_OF_PAGE_IN_FW_QUEUE_BCN << - RSVD_FW_QUEUE_PAGE_BCN_SHIFT| - NUM_OF_PAGE_IN_FW_QUEUE_PUB << - RSVD_FW_QUEUE_PAGE_PUB_SHIFT); - - rtl8192_tx_enable(dev); - rtl8192_rx_enable(dev); - ulRegRead = (0xFFF00000 & read_nic_dword(dev, RRSR)) | + rtl92e_writeb(dev, CMDR, CR_RE | CR_TE); + + rtl92e_writeb(dev, PCIF, ((MXDMA2_NoLimit<<MXDMA2_RX_SHIFT) | + (MXDMA2_NoLimit<<MXDMA2_TX_SHIFT))); + rtl92e_writel(dev, MAC0, ((u32 *)dev->dev_addr)[0]); + rtl92e_writew(dev, MAC4, ((u16 *)(dev->dev_addr + 4))[0]); + rtl92e_writel(dev, RCR, priv->ReceiveConfig); + + rtl92e_writel(dev, RQPN1, NUM_OF_PAGE_IN_FW_QUEUE_BK << + RSVD_FW_QUEUE_PAGE_BK_SHIFT | + NUM_OF_PAGE_IN_FW_QUEUE_BE << + RSVD_FW_QUEUE_PAGE_BE_SHIFT | + NUM_OF_PAGE_IN_FW_QUEUE_VI << + RSVD_FW_QUEUE_PAGE_VI_SHIFT | + NUM_OF_PAGE_IN_FW_QUEUE_VO << + RSVD_FW_QUEUE_PAGE_VO_SHIFT); + rtl92e_writel(dev, RQPN2, NUM_OF_PAGE_IN_FW_QUEUE_MGNT << + RSVD_FW_QUEUE_PAGE_MGNT_SHIFT); + rtl92e_writel(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW | + NUM_OF_PAGE_IN_FW_QUEUE_BCN << + RSVD_FW_QUEUE_PAGE_BCN_SHIFT| + NUM_OF_PAGE_IN_FW_QUEUE_PUB << + RSVD_FW_QUEUE_PAGE_PUB_SHIFT); + + rtl92e_tx_enable(dev); + rtl92e_rx_enable(dev); + ulRegRead = (0xFFF00000 & rtl92e_readl(dev, RRSR)) | RATE_ALL_OFDM_AG | RATE_ALL_CCK; - write_nic_dword(dev, RRSR, ulRegRead); - write_nic_dword(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK)); + rtl92e_writel(dev, RRSR, ulRegRead); + rtl92e_writel(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK)); - write_nic_byte(dev, ACK_TIMEOUT, 0x30); + rtl92e_writeb(dev, ACK_TIMEOUT, 0x30); if (priv->ResetProgress == RESET_TYPE_NORESET) - rtl8192_SetWirelessMode(dev, priv->rtllib->mode); - CamResetAllEntry(dev); + rtl92e_set_wireless_mode(dev, priv->rtllib->mode); + rtl92e_cam_reset(dev); { u8 SECR_value = 0x0; SECR_value |= SCR_TxEncEnable; SECR_value |= SCR_RxDecEnable; SECR_value |= SCR_NoSKMC; - write_nic_byte(dev, SECR, SECR_value); + rtl92e_writeb(dev, SECR, SECR_value); } - write_nic_word(dev, ATIMWND, 2); - write_nic_word(dev, BCN_INTERVAL, 100); + rtl92e_writew(dev, ATIMWND, 2); + rtl92e_writew(dev, BCN_INTERVAL, 100); { int i; for (i = 0; i < QOS_QUEUE_NUM; i++) - write_nic_dword(dev, WDCAPARA_ADD[i], 0x005e4332); + rtl92e_writel(dev, WDCAPARA_ADD[i], 0x005e4332); } - write_nic_byte(dev, 0xbe, 0xc0); + rtl92e_writeb(dev, 0xbe, 0xc0); - rtl8192_phy_configmac(dev); + rtl92e_config_mac(dev); if (priv->card_8192_version > (u8) VERSION_8190_BD) { - rtl8192_phy_getTxPower(dev); - rtl8192_phy_setTxPower(dev, priv->chan); + rtl92e_get_tx_power(dev); + rtl92e_set_tx_power(dev, priv->chan); } - tmpvalue = read_nic_byte(dev, IC_VERRSION); + tmpvalue = rtl92e_readb(dev, IC_VERRSION); priv->IC_Cut = tmpvalue; RT_TRACE(COMP_INIT, "priv->IC_Cut= 0x%x\n", priv->IC_Cut); if (priv->IC_Cut >= IC_VersionCut_D) { @@ -850,7 +852,7 @@ start: } RT_TRACE(COMP_INIT, "Load Firmware!\n"); - bfirmwareok = init_firmware(dev); + bfirmwareok = rtl92e_init_fw(dev); if (!bfirmwareok) { if (retry_times < 10) { retry_times++; @@ -863,37 +865,34 @@ start: RT_TRACE(COMP_INIT, "Load Firmware finished!\n"); if (priv->ResetProgress == RESET_TYPE_NORESET) { RT_TRACE(COMP_INIT, "RF Config Started!\n"); - rtStatus = rtl8192_phy_RFConfig(dev); + rtStatus = rtl92e_config_phy(dev); if (!rtStatus) { netdev_info(dev, "RF Config failed\n"); return rtStatus; } RT_TRACE(COMP_INIT, "RF Config Finished!\n"); } - rtl8192_phy_updateInitGain(dev); - rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1); - rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1); + rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bCCKEn, 0x1); + rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1); - write_nic_byte(dev, 0x87, 0x0); + rtl92e_writeb(dev, 0x87, 0x0); if (priv->RegRfOff) { RT_TRACE((COMP_INIT | COMP_RF | COMP_POWER), "%s(): Turn off RF for RegRfOff ----------\n", __func__); - MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_SW, true); + rtl92e_set_rf_state(dev, eRfOff, RF_CHANGE_BY_SW); } else if (priv->rtllib->RfOffReason > RF_CHANGE_BY_PS) { RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER), "%s(): Turn off RF for RfOffReason(%d) ----------\n", __func__, priv->rtllib->RfOffReason); - MgntActSet_RF_State(dev, eRfOff, priv->rtllib->RfOffReason, - true); + rtl92e_set_rf_state(dev, eRfOff, priv->rtllib->RfOffReason); } else if (priv->rtllib->RfOffReason >= RF_CHANGE_BY_IPS) { RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER), "%s(): Turn off RF for RfOffReason(%d) ----------\n", __func__, priv->rtllib->RfOffReason); - MgntActSet_RF_State(dev, eRfOff, priv->rtllib->RfOffReason, - true); + rtl92e_set_rf_state(dev, eRfOff, priv->rtllib->RfOffReason); } else { RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER), "%s(): RF-ON\n", __func__); @@ -907,13 +906,13 @@ start: priv->Rf_Mode = RF_OP_By_SW_3wire; if (priv->ResetProgress == RESET_TYPE_NORESET) { - dm_initialize_txpower_tracking(dev); + rtl92e_dm_init_txpower_tracking(dev); if (priv->IC_Cut >= IC_VersionCut_D) { - tmpRegA = rtl8192_QueryBBReg(dev, - rOFDM0_XATxIQImbalance, bMaskDWord); - tmpRegC = rtl8192_QueryBBReg(dev, - rOFDM0_XCTxIQImbalance, bMaskDWord); + tmpRegA = rtl92e_get_bb_reg(dev, rOFDM0_XATxIQImbalance, + bMaskDWord); + tmpRegC = rtl92e_get_bb_reg(dev, rOFDM0_XCTxIQImbalance, + bMaskDWord); for (i = 0; i < TxBBGainTableLength; i++) { if (tmpRegA == dm_tx_bb_gain[i]) { priv->rfa_txpowertrackingindex = (u8)i; @@ -925,8 +924,8 @@ start: } } - TempCCk = rtl8192_QueryBBReg(dev, - rCCK0_TxFilter1, bMaskByte2); + TempCCk = rtl92e_get_bb_reg(dev, rCCK0_TxFilter1, + bMaskByte2); for (i = 0; i < CCKTxBBGainTableLength; i++) { if (TempCCk == dm_cck_tx_bb_gain[i][0]) { @@ -953,7 +952,7 @@ start: priv->btxpower_tracking = false; } } - rtl8192_irq_enable(dev); + rtl92e_irq_enable(dev); end: priv->being_init_adapter = false; return rtStatus; @@ -968,27 +967,27 @@ static void rtl8192_net_update(struct net_device *dev) u16 rate_config = 0; net = &priv->rtllib->current_network; - rtl8192_config_rate(dev, &rate_config); + rtl92e_config_rate(dev, &rate_config); priv->dot11CurrentPreambleMode = PREAMBLE_AUTO; priv->basic_rate = rate_config &= 0x15f; - write_nic_dword(dev, BSSIDR, ((u32 *)net->bssid)[0]); - write_nic_word(dev, BSSIDR+4, ((u16 *)net->bssid)[2]); + rtl92e_writel(dev, BSSIDR, ((u32 *)net->bssid)[0]); + rtl92e_writew(dev, BSSIDR+4, ((u16 *)net->bssid)[2]); if (priv->rtllib->iw_mode == IW_MODE_ADHOC) { - write_nic_word(dev, ATIMWND, 2); - write_nic_word(dev, BCN_DMATIME, 256); - write_nic_word(dev, BCN_INTERVAL, net->beacon_interval); - write_nic_word(dev, BCN_DRV_EARLY_INT, 10); - write_nic_byte(dev, BCN_ERR_THRESH, 100); + rtl92e_writew(dev, ATIMWND, 2); + rtl92e_writew(dev, BCN_DMATIME, 256); + rtl92e_writew(dev, BCN_INTERVAL, net->beacon_interval); + rtl92e_writew(dev, BCN_DRV_EARLY_INT, 10); + rtl92e_writeb(dev, BCN_ERR_THRESH, 100); BcnTimeCfg |= (BcnCW<<BCN_TCFG_CW_SHIFT); BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS; - write_nic_word(dev, BCN_TCFG, BcnTimeCfg); + rtl92e_writew(dev, BCN_TCFG, BcnTimeCfg); } } -void rtl8192_link_change(struct net_device *dev) +void rtl92e_link_change(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); struct rtllib_device *ieee = priv->rtllib; @@ -1001,16 +1000,16 @@ void rtl8192_link_change(struct net_device *dev) priv->ops->update_ratr_table(dev); if ((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type)) - EnableHWSecurityConfig8192(dev); + rtl92e_enable_hw_security_config(dev); } else { - write_nic_byte(dev, 0x173, 0); + rtl92e_writeb(dev, 0x173, 0); } rtl8192e_update_msr(dev); if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) { u32 reg = 0; - reg = read_nic_dword(dev, RCR); + reg = rtl92e_readl(dev, RCR); if (priv->rtllib->state == RTLLIB_LINKED) { if (ieee->IntelPromiscuousModeInfo.bPromiscuousOn) ; @@ -1019,12 +1018,12 @@ void rtl8192_link_change(struct net_device *dev) } else priv->ReceiveConfig = reg &= ~RCR_CBSSID; - write_nic_dword(dev, RCR, reg); + rtl92e_writel(dev, RCR, reg); } } -void rtl8192_AllowAllDestAddr(struct net_device *dev, - bool bAllowAllDA, bool WriteIntoReg) +void rtl92e_set_monitor_mode(struct net_device *dev, bool bAllowAllDA, + bool WriteIntoReg) { struct r8192_priv *priv = rtllib_priv(dev); @@ -1034,7 +1033,7 @@ void rtl8192_AllowAllDestAddr(struct net_device *dev, priv->ReceiveConfig &= ~RCR_AAP; if (WriteIntoReg) - write_nic_dword(dev, RCR, priv->ReceiveConfig); + rtl92e_writel(dev, RCR, priv->ReceiveConfig); } static u8 MRateToHwRate8190Pci(u8 rate) @@ -1188,8 +1187,8 @@ static u8 rtl8192_QueryIsShort(u8 TxHT, u8 TxRate, struct cb_desc *tcb_desc) return tmp_Short; } -void rtl8192_tx_fill_desc(struct net_device *dev, struct tx_desc *pdesc, - struct cb_desc *cb_desc, struct sk_buff *skb) +void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc, + struct cb_desc *cb_desc, struct sk_buff *skb) { struct r8192_priv *priv = rtllib_priv(dev); dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len, @@ -1297,9 +1296,8 @@ void rtl8192_tx_fill_desc(struct net_device *dev, struct tx_desc *pdesc, pdesc->TxBuffAddr = mapping; } -void rtl8192_tx_fill_cmd_desc(struct net_device *dev, - struct tx_desc_cmd *entry, - struct cb_desc *cb_desc, struct sk_buff *skb) +void rtl92e_fill_tx_cmd_desc(struct net_device *dev, struct tx_desc_cmd *entry, + struct cb_desc *cb_desc, struct sk_buff *skb) { struct r8192_priv *priv = rtllib_priv(dev); dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len, @@ -1517,8 +1515,9 @@ static void rtl8192_query_rxphystatus( pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon; pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA; if (check_reg824 == 0) { - reg824_bit9 = rtl8192_QueryBBReg(priv->rtllib->dev, - rFPGA0_XA_HSSIParameter2, 0x200); + reg824_bit9 = rtl92e_get_bb_reg(priv->rtllib->dev, + rFPGA0_XA_HSSIParameter2, + 0x200); check_reg824 = 1; } @@ -1586,7 +1585,7 @@ static void rtl8192_query_rxphystatus( } } - pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all); + pwdb_all = rtl92e_rx_db_to_percent(rx_pwr_all); pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all; pstats->RecvSignalPower = rx_pwr_all; @@ -1626,7 +1625,7 @@ static void rtl8192_query_rxphystatus( rx_snrX /= 2; priv->stats.rxSNRdB[i] = (long)rx_snrX; - RSSI = rtl819x_query_rxpwrpercentage(rx_pwr[i]); + RSSI = rtl92e_rx_db_to_percent(rx_pwr[i]); if (priv->brfpath_rxenable[i]) total_rssi += RSSI; @@ -1639,7 +1638,7 @@ static void rtl8192_query_rxphystatus( rx_pwr_all = (((pofdm_buf->pwdb_all) >> 1) & 0x7f) - 106; - pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all); + pwdb_all = rtl92e_rx_db_to_percent(rx_pwr_all); pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all; pstats->RxPower = precord_stats->RxPower = rx_pwr_all; @@ -1656,7 +1655,7 @@ static void rtl8192_query_rxphystatus( rx_evmX /= 2; - evm = rtl819x_evm_dbtopercentage(rx_evmX); + evm = rtl92e_evm_db_to_percent(rx_evmX); if (bpacket_match_bssid) { if (i == 0) { pstats->SignalQuality = (u8)(evm & @@ -1732,8 +1731,8 @@ static void rtl8192_process_phyinfo(struct r8192_priv *priv, u8 *buffer, slide_rssi_index = 0; tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics; - priv->stats.signal_strength = rtl819x_translate_todbm(priv, - (u8)tmp_val); + priv->stats.signal_strength = rtl92e_translate_to_dbm(priv, + (u8)tmp_val); curr_st->rssi = priv->stats.signal_strength; if (!prev_st->bPacketMatchBSSID) { if (!prev_st->bToSelfBA) @@ -1746,8 +1745,7 @@ static void rtl8192_process_phyinfo(struct r8192_priv *priv, u8 *buffer, priv->stats.num_process_phyinfo++; if (!prev_st->bIsCCK && prev_st->bPacketToSelf) { for (rfpath = RF90_PATH_A; rfpath < RF90_PATH_C; rfpath++) { - if (!rtl8192_phy_CheckIsLegalRFPath(priv->rtllib->dev, - rfpath)) + if (!rtl92e_is_legal_rf_path(priv->rtllib->dev, rfpath)) continue; RT_TRACE(COMP_DBG, "Jacken -> pPreviousstats->RxMIMOSignalStrength[rfpath] = %d\n", @@ -1822,7 +1820,7 @@ static void rtl8192_process_phyinfo(struct r8192_priv *priv, u8 *buffer, (RX_SMOOTH-1)) + (prev_st->RxPWDBAll)) / (RX_SMOOTH); } - rtl819x_update_rxsignalstatistics8190pci(priv, prev_st); + rtl92e_update_rx_statistics(priv, prev_st); } if (prev_st->SignalQuality != 0) { @@ -1909,7 +1907,7 @@ static void rtl8192_TranslateRxSignalStuff(struct net_device *dev, rtl8192_query_rxphystatus(priv, pstats, pdesc, pdrvinfo, &previous_stats, bpacket_match_bssid, bpacket_toself, bPacketBeacon, bToSelfBA); - rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats); + rtl92e_copy_mpdu_stats(pstats, &previous_stats); } static void rtl8192_UpdateReceivedRateHistogramStatistics( @@ -2025,10 +2023,8 @@ static void rtl8192_UpdateReceivedRateHistogramStatistics( priv->stats.received_rate_histogram[rcvType][rateIndex]++; } -bool rtl8192_rx_query_status_desc(struct net_device *dev, - struct rtllib_rx_stats *stats, - struct rx_desc *pdesc, - struct sk_buff *skb) +bool rtl92e_get_rx_stats(struct net_device *dev, struct rtllib_rx_stats *stats, + struct rx_desc *pdesc, struct sk_buff *skb) { struct r8192_priv *priv = rtllib_priv(dev); struct rx_fwinfo *pDrvInfo = NULL; @@ -2072,9 +2068,9 @@ bool rtl8192_rx_query_status_desc(struct net_device *dev, (pDrvInfo->FirstAGGR == 1); stats->TimeStampLow = pDrvInfo->TSFL; - stats->TimeStampHigh = read_nic_dword(dev, TSFR+4); + stats->TimeStampHigh = rtl92e_readl(dev, TSFR+4); - rtl819x_UpdateRxPktTimeStamp(dev, stats); + rtl92e_update_rx_pkt_timestamp(dev, stats); if ((stats->RxBufShift + stats->RxDrvInfoSize) > 0) stats->bShift = 1; @@ -2098,7 +2094,7 @@ bool rtl8192_rx_query_status_desc(struct net_device *dev, return true; } -void rtl8192_halt_adapter(struct net_device *dev, bool reset) +void rtl92e_stop_adapter(struct net_device *dev, bool reset) { struct r8192_priv *priv = rtllib_priv(dev); int i; @@ -2111,7 +2107,7 @@ void rtl8192_halt_adapter(struct net_device *dev, bool reset) if (!priv->rtllib->bSupportRemoteWakeUp) { u1bTmp = 0x0; - write_nic_byte(dev, CMDR, u1bTmp); + rtl92e_writeb(dev, CMDR, u1bTmp); } mdelay(20); @@ -2122,18 +2118,18 @@ void rtl8192_halt_adapter(struct net_device *dev, bool reset) priv->bHwRfOffAction = 2; if (!priv->rtllib->bSupportRemoteWakeUp) { - PHY_SetRtl8192eRfOff(dev); - ulRegRead = read_nic_dword(dev, CPU_GEN); + rtl92e_set_rf_off(dev); + ulRegRead = rtl92e_readl(dev, CPU_GEN); ulRegRead |= CPU_GEN_SYSTEM_RESET; - write_nic_dword(dev, CPU_GEN, ulRegRead); + rtl92e_writel(dev, CPU_GEN, ulRegRead); } else { - write_nic_dword(dev, WFCRC0, 0xffffffff); - write_nic_dword(dev, WFCRC1, 0xffffffff); - write_nic_dword(dev, WFCRC2, 0xffffffff); + rtl92e_writel(dev, WFCRC0, 0xffffffff); + rtl92e_writel(dev, WFCRC1, 0xffffffff); + rtl92e_writel(dev, WFCRC2, 0xffffffff); - write_nic_byte(dev, PMR, 0x5); - write_nic_byte(dev, MacBlkCtrl, 0xa); + rtl92e_writeb(dev, PMR, 0x5); + rtl92e_writeb(dev, MacBlkCtrl, 0xa); } } @@ -2145,7 +2141,7 @@ void rtl8192_halt_adapter(struct net_device *dev, bool reset) skb_queue_purge(&priv->skb_queue); } -void rtl8192_update_ratr_table(struct net_device *dev) +void rtl92e_update_ratr_table(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); struct rtllib_device *ieee = priv->rtllib; @@ -2154,7 +2150,7 @@ void rtl8192_update_ratr_table(struct net_device *dev) u16 rate_config = 0; u8 rate_index = 0; - rtl8192_config_rate(dev, &rate_config); + rtl92e_config_rate(dev, &rate_config); ratr_value = rate_config | *pMcsRate << 12; switch (ieee->mode) { case IEEE_A: @@ -2188,12 +2184,12 @@ void rtl8192_update_ratr_table(struct net_device *dev) else if (!ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI20MHz) ratr_value |= 0x80000000; - write_nic_dword(dev, RATR0+rate_index*4, ratr_value); - write_nic_byte(dev, UFWP, 1); + rtl92e_writel(dev, RATR0+rate_index*4, ratr_value); + rtl92e_writeb(dev, UFWP, 1); } void -rtl8192_InitializeVariables(struct net_device *dev) +rtl92e_init_variables(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); @@ -2227,66 +2223,65 @@ rtl8192_InitializeVariables(struct net_device *dev) priv->bfirst_after_down = false; } -void rtl8192_EnableInterrupt(struct net_device *dev) +void rtl92e_enable_irq(struct net_device *dev) { struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); priv->irq_enabled = 1; - write_nic_dword(dev, INTA_MASK, priv->irq_mask[0]); + rtl92e_writel(dev, INTA_MASK, priv->irq_mask[0]); } -void rtl8192_DisableInterrupt(struct net_device *dev) +void rtl92e_disable_irq(struct net_device *dev) { struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); - write_nic_dword(dev, INTA_MASK, 0); + rtl92e_writel(dev, INTA_MASK, 0); priv->irq_enabled = 0; } -void rtl8192_ClearInterrupt(struct net_device *dev) +void rtl92e_clear_irq(struct net_device *dev) { u32 tmp = 0; - tmp = read_nic_dword(dev, ISR); - write_nic_dword(dev, ISR, tmp); + tmp = rtl92e_readl(dev, ISR); + rtl92e_writel(dev, ISR, tmp); } -void rtl8192_enable_rx(struct net_device *dev) +void rtl92e_enable_rx(struct net_device *dev) { struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); - write_nic_dword(dev, RDQDA, priv->rx_ring_dma[RX_MPDU_QUEUE]); + rtl92e_writel(dev, RDQDA, priv->rx_ring_dma[RX_MPDU_QUEUE]); } static const u32 TX_DESC_BASE[] = { BKQDA, BEQDA, VIQDA, VOQDA, HCCAQDA, CQDA, MQDA, HQDA, BQDA }; -void rtl8192_enable_tx(struct net_device *dev) +void rtl92e_enable_tx(struct net_device *dev) { struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); u32 i; for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) - write_nic_dword(dev, TX_DESC_BASE[i], priv->tx_ring[i].dma); + rtl92e_writel(dev, TX_DESC_BASE[i], priv->tx_ring[i].dma); } -void rtl8192_interrupt_recognized(struct net_device *dev, u32 *p_inta, - u32 *p_intb) +void rtl92e_ack_irq(struct net_device *dev, u32 *p_inta, u32 *p_intb) { - *p_inta = read_nic_dword(dev, ISR); - write_nic_dword(dev, ISR, *p_inta); + *p_inta = rtl92e_readl(dev, ISR); + rtl92e_writel(dev, ISR, *p_inta); } -bool rtl8192_HalRxCheckStuck(struct net_device *dev) +bool rtl92e_is_rx_stuck(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); - u16 RegRxCounter = read_nic_word(dev, 0x130); + u16 RegRxCounter = rtl92e_readw(dev, 0x130); bool bStuck = false; static u8 rx_chk_cnt; u32 SlotIndex = 0, TotalRxStuckCount = 0; @@ -2347,11 +2342,11 @@ bool rtl8192_HalRxCheckStuck(struct net_device *dev) return bStuck; } -bool rtl8192_HalTxCheckStuck(struct net_device *dev) +bool rtl92e_is_tx_stuck(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); bool bStuck = false; - u16 RegTxCounter = read_nic_word(dev, 0x128); + u16 RegTxCounter = rtl92e_readw(dev, 0x128); RT_TRACE(COMP_RESET, "%s():RegTxCounter is %d,TxCounter is %d\n", __func__, RegTxCounter, priv->TxCounter); @@ -2364,7 +2359,7 @@ bool rtl8192_HalTxCheckStuck(struct net_device *dev) return bStuck; } -bool rtl8192_GetNmodeSupportBySecCfg(struct net_device *dev) +bool rtl92e_get_nmode_support_by_sec(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); struct rtllib_device *ieee = priv->rtllib; @@ -2378,22 +2373,10 @@ bool rtl8192_GetNmodeSupportBySecCfg(struct net_device *dev) } } -bool rtl8192_GetHalfNmodeSupportByAPs(struct net_device *dev) +bool rtl92e_is_halfn_supported_by_ap(struct net_device *dev) { - bool Reval; struct r8192_priv *priv = rtllib_priv(dev); struct rtllib_device *ieee = priv->rtllib; - if (ieee->bHalfWirelessN24GMode == true) - Reval = true; - else - Reval = false; - - return Reval; -} - -void ActUpdateChannelAccessSetting(struct net_device *dev, - enum wireless_mode WirelessMode, - struct channel_access_setting *ChnlAccessSetting) -{ + return ieee->bHalfWirelessN24GMode; } diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.h index 4f1b312e90f4..6bd6b3a4fcea 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.h +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.h @@ -27,35 +27,30 @@ #include "r8190P_def.h" -bool rtl8192_GetHalfNmodeSupportByAPs(struct net_device *dev); -bool rtl8192_GetNmodeSupportBySecCfg(struct net_device *dev); -bool rtl8192_HalTxCheckStuck(struct net_device *dev); -bool rtl8192_HalRxCheckStuck(struct net_device *dev); -void rtl8192_interrupt_recognized(struct net_device *dev, u32 *p_inta, - u32 *p_intb); -void rtl8192_enable_rx(struct net_device *dev); -void rtl8192_enable_tx(struct net_device *dev); -void rtl8192_EnableInterrupt(struct net_device *dev); -void rtl8192_DisableInterrupt(struct net_device *dev); -void rtl8192_ClearInterrupt(struct net_device *dev); -void rtl8192_InitializeVariables(struct net_device *dev); -void rtl8192e_start_beacon(struct net_device *dev); -void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val); -void rtl8192_get_eeprom_size(struct net_device *dev); -bool rtl8192_adapter_start(struct net_device *dev); -void rtl8192_link_change(struct net_device *dev); -void rtl8192_AllowAllDestAddr(struct net_device *dev, bool bAllowAllDA, - bool WriteIntoReg); -void rtl8192_tx_fill_desc(struct net_device *dev, struct tx_desc *pdesc, - struct cb_desc *cb_desc, - struct sk_buff *skb); -void rtl8192_tx_fill_cmd_desc(struct net_device *dev, - struct tx_desc_cmd *entry, - struct cb_desc *cb_desc, struct sk_buff *skb); -bool rtl8192_rx_query_status_desc(struct net_device *dev, - struct rtllib_rx_stats *stats, - struct rx_desc *pdesc, - struct sk_buff *skb); -void rtl8192_halt_adapter(struct net_device *dev, bool reset); -void rtl8192_update_ratr_table(struct net_device *dev); +bool rtl92e_is_halfn_supported_by_ap(struct net_device *dev); +bool rtl92e_get_nmode_support_by_sec(struct net_device *dev); +bool rtl92e_is_tx_stuck(struct net_device *dev); +bool rtl92e_is_rx_stuck(struct net_device *dev); +void rtl92e_ack_irq(struct net_device *dev, u32 *p_inta, u32 *p_intb); +void rtl92e_enable_rx(struct net_device *dev); +void rtl92e_enable_tx(struct net_device *dev); +void rtl92e_enable_irq(struct net_device *dev); +void rtl92e_disable_irq(struct net_device *dev); +void rtl92e_clear_irq(struct net_device *dev); +void rtl92e_init_variables(struct net_device *dev); +void rtl92e_start_beacon(struct net_device *dev); +void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val); +void rtl92e_get_eeprom_size(struct net_device *dev); +bool rtl92e_start_adapter(struct net_device *dev); +void rtl92e_link_change(struct net_device *dev); +void rtl92e_set_monitor_mode(struct net_device *dev, bool bAllowAllDA, + bool WriteIntoReg); +void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc, + struct cb_desc *cb_desc, struct sk_buff *skb); +void rtl92e_fill_tx_cmd_desc(struct net_device *dev, struct tx_desc_cmd *entry, + struct cb_desc *cb_desc, struct sk_buff *skb); +bool rtl92e_get_rx_stats(struct net_device *dev, struct rtllib_rx_stats *stats, + struct rx_desc *pdesc, struct sk_buff *skb); +void rtl92e_stop_adapter(struct net_device *dev, bool reset); +void rtl92e_update_ratr_table(struct net_device *dev); #endif diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c index 17d2a1540cc8..5c527c419bc9 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c @@ -23,7 +23,7 @@ #include "r8192E_firmware.h" #include <linux/firmware.h> -void firmware_init_param(struct net_device *dev) +void rtl92e_init_fw_param(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); struct rt_firmware *pfirmware = priv->pFirmware; @@ -46,7 +46,7 @@ static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address, struct cb_desc *tcb_desc; u8 bLastIniPkt; - firmware_init_param(dev); + rtl92e_init_fw_param(dev); frag_threshold = pfirmware->cmdpacket_frag_thresold; do { if ((buffer_len - frag_offset) > frag_threshold) { @@ -96,7 +96,7 @@ static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address, } while (frag_offset < buffer_len); - write_nic_byte(dev, TPPoll, TPPoll_CQ); + rtl92e_writeb(dev, TPPoll, TPPoll_CQ); return true; } @@ -109,7 +109,7 @@ static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev) timeout = jiffies + msecs_to_jiffies(200); while (time_before(jiffies, timeout)) { - CPU_status = read_nic_dword(dev, CPU_GEN); + CPU_status = rtl92e_readl(dev, CPU_GEN); if (CPU_status & CPU_GEN_PUT_CODE_OK) break; mdelay(2); @@ -122,14 +122,14 @@ static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev) RT_TRACE(COMP_FIRMWARE, "Download Firmware: Put code ok!\n"); } - CPU_status = read_nic_dword(dev, CPU_GEN); - write_nic_byte(dev, CPU_GEN, - (u8)((CPU_status|CPU_GEN_PWR_STB_CPU)&0xff)); + CPU_status = rtl92e_readl(dev, CPU_GEN); + rtl92e_writeb(dev, CPU_GEN, + (u8)((CPU_status|CPU_GEN_PWR_STB_CPU)&0xff)); mdelay(1); timeout = jiffies + msecs_to_jiffies(200); while (time_before(jiffies, timeout)) { - CPU_status = read_nic_dword(dev, CPU_GEN); + CPU_status = rtl92e_readl(dev, CPU_GEN); if (CPU_status&CPU_GEN_BOOT_RDY) break; mdelay(2); @@ -158,7 +158,7 @@ static bool CPUcheck_firmware_ready(struct net_device *dev) timeout = jiffies + msecs_to_jiffies(20); while (time_before(jiffies, timeout)) { - CPU_status = read_nic_dword(dev, CPU_GEN); + CPU_status = rtl92e_readl(dev, CPU_GEN); if (CPU_status&CPU_GEN_FIRM_RDY) break; mdelay(2); @@ -223,7 +223,7 @@ static bool firmware_check_ready(struct net_device *dev, return rt_status; } -bool init_firmware(struct net_device *dev) +bool rtl92e_init_fw(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); bool rt_status = true; diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h index ef232d2c34e6..4c464eaee69f 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h @@ -59,7 +59,7 @@ struct rt_firmware { u16 firmware_buf_size[MAX_FW_INIT_STEP]; }; -bool init_firmware(struct net_device *dev); -extern void firmware_init_param(struct net_device *dev); +bool rtl92e_init_fw(struct net_device *dev); +extern void rtl92e_init_fw_param(struct net_device *dev); #endif diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h index 43c3fb859d10..c81832dcf181 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h @@ -119,10 +119,10 @@ enum _RTL8192Pci_HW { #define EPROM_CMD_NORMAL 0 #define EPROM_CMD_LOAD 1 #define EPROM_CMD_PROGRAM 2 -#define EPROM_CS_SHIFT 3 -#define EPROM_CK_SHIFT 2 -#define EPROM_W_SHIFT 1 -#define EPROM_R_SHIFT 0 +#define EPROM_CS_BIT 3 +#define EPROM_CK_BIT 2 +#define EPROM_W_BIT 1 +#define EPROM_R_BIT 0 AFR = 0x010, #define AFR_CardBEn (1<<0) diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c index 32135235f3e2..3a15a0f5b479 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c @@ -64,7 +64,7 @@ static u32 rtl8192_CalculateBitShift(u32 dwBitMask) return i; } -u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device *dev, u32 eRFPath) +u8 rtl92e_is_legal_rf_path(struct net_device *dev, u32 eRFPath) { u8 ret = 1; struct r8192_priv *priv = rtllib_priv(dev); @@ -80,27 +80,27 @@ u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device *dev, u32 eRFPath) return ret; } -void rtl8192_setBBreg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask, - u32 dwData) +void rtl92e_set_bb_reg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask, + u32 dwData) { u32 OriginalValue, BitShift, NewValue; if (dwBitMask != bMaskDWord) { - OriginalValue = read_nic_dword(dev, dwRegAddr); + OriginalValue = rtl92e_readl(dev, dwRegAddr); BitShift = rtl8192_CalculateBitShift(dwBitMask); NewValue = (((OriginalValue) & (~dwBitMask)) | (dwData << BitShift)); - write_nic_dword(dev, dwRegAddr, NewValue); + rtl92e_writel(dev, dwRegAddr, NewValue); } else - write_nic_dword(dev, dwRegAddr, dwData); + rtl92e_writel(dev, dwRegAddr, dwData); } -u32 rtl8192_QueryBBReg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask) +u32 rtl92e_get_bb_reg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask) { u32 Ret = 0, OriginalValue, BitShift; - OriginalValue = read_nic_dword(dev, dwRegAddr); + OriginalValue = rtl92e_readl(dev, dwRegAddr); BitShift = rtl8192_CalculateBitShift(dwBitMask); Ret = (OriginalValue & dwBitMask) >> BitShift; @@ -117,19 +117,19 @@ static u32 rtl8192_phy_RFSerialRead(struct net_device *dev, Offset &= 0x3f; if (priv->rf_chip == RF_8256) { - rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0); + rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0); if (Offset >= 31) { priv->RfReg0Value[eRFPath] |= 0x140; - rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, - bMaskDWord, - (priv->RfReg0Value[eRFPath]<<16)); + rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset, + bMaskDWord, + (priv->RfReg0Value[eRFPath]<<16)); NewOffset = Offset - 30; } else if (Offset >= 16) { priv->RfReg0Value[eRFPath] |= 0x100; priv->RfReg0Value[eRFPath] &= (~0x40); - rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, - bMaskDWord, - (priv->RfReg0Value[eRFPath]<<16)); + rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset, + bMaskDWord, + (priv->RfReg0Value[eRFPath]<<16)); NewOffset = Offset - 15; } else @@ -139,23 +139,23 @@ static u32 rtl8192_phy_RFSerialRead(struct net_device *dev, "check RF type here, need to be 8256\n"); NewOffset = Offset; } - rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bLSSIReadAddress, - NewOffset); - rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bLSSIReadEdge, 0x0); - rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bLSSIReadEdge, 0x1); + rtl92e_set_bb_reg(dev, pPhyReg->rfHSSIPara2, bLSSIReadAddress, + NewOffset); + rtl92e_set_bb_reg(dev, pPhyReg->rfHSSIPara2, bLSSIReadEdge, 0x0); + rtl92e_set_bb_reg(dev, pPhyReg->rfHSSIPara2, bLSSIReadEdge, 0x1); mdelay(1); - ret = rtl8192_QueryBBReg(dev, pPhyReg->rfLSSIReadBack, - bLSSIReadBackData); + ret = rtl92e_get_bb_reg(dev, pPhyReg->rfLSSIReadBack, + bLSSIReadBackData); if (priv->rf_chip == RF_8256) { priv->RfReg0Value[eRFPath] &= 0xebf; - rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord, - (priv->RfReg0Value[eRFPath] << 16)); + rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset, bMaskDWord, + (priv->RfReg0Value[eRFPath] << 16)); - rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3); + rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3); } @@ -173,20 +173,20 @@ static void rtl8192_phy_RFSerialWrite(struct net_device *dev, Offset &= 0x3f; if (priv->rf_chip == RF_8256) { - rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0); + rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0); if (Offset >= 31) { priv->RfReg0Value[eRFPath] |= 0x140; - rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, - bMaskDWord, - (priv->RfReg0Value[eRFPath] << 16)); + rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset, + bMaskDWord, + (priv->RfReg0Value[eRFPath] << 16)); NewOffset = Offset - 30; } else if (Offset >= 16) { priv->RfReg0Value[eRFPath] |= 0x100; priv->RfReg0Value[eRFPath] &= (~0x40); - rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, - bMaskDWord, - (priv->RfReg0Value[eRFPath] << 16)); + rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset, + bMaskDWord, + (priv->RfReg0Value[eRFPath] << 16)); NewOffset = Offset - 15; } else NewOffset = Offset; @@ -198,7 +198,7 @@ static void rtl8192_phy_RFSerialWrite(struct net_device *dev, DataAndAddr = (Data<<16) | (NewOffset&0x3f); - rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr); + rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr); if (Offset == 0x0) priv->RfReg0Value[eRFPath] = Data; @@ -206,23 +206,21 @@ static void rtl8192_phy_RFSerialWrite(struct net_device *dev, if (priv->rf_chip == RF_8256) { if (Offset != 0) { priv->RfReg0Value[eRFPath] &= 0xebf; - rtl8192_setBBreg( - dev, - pPhyReg->rf3wireOffset, - bMaskDWord, - (priv->RfReg0Value[eRFPath] << 16)); + rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset, + bMaskDWord, + (priv->RfReg0Value[eRFPath] << 16)); } - rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3); + rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3); } } -void rtl8192_phy_SetRFReg(struct net_device *dev, enum rf90_radio_path eRFPath, - u32 RegAddr, u32 BitMask, u32 Data) +void rtl92e_set_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath, + u32 RegAddr, u32 BitMask, u32 Data) { struct r8192_priv *priv = rtllib_priv(dev); u32 Original_Value, BitShift, New_Value; - if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath)) + if (!rtl92e_is_legal_rf_path(dev, eRFPath)) return; if (priv->rtllib->eRFPowerState != eRfOn && !priv->being_init_adapter) return; @@ -256,13 +254,13 @@ void rtl8192_phy_SetRFReg(struct net_device *dev, enum rf90_radio_path eRFPath, } } -u32 rtl8192_phy_QueryRFReg(struct net_device *dev, enum rf90_radio_path eRFPath, - u32 RegAddr, u32 BitMask) +u32 rtl92e_get_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath, + u32 RegAddr, u32 BitMask) { u32 Original_Value, Readback_Value, BitShift; struct r8192_priv *priv = rtllib_priv(dev); - if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath)) + if (!rtl92e_is_legal_rf_path(dev, eRFPath)) return 0; if (priv->rtllib->eRFPowerState != eRfOn && !priv->being_init_adapter) return 0; @@ -289,20 +287,20 @@ static u32 phy_FwRFSerialRead(struct net_device *dev, Data |= ((Offset & 0xFF) << 12); Data |= ((eRFPath & 0x3) << 20); Data |= 0x80000000; - while (read_nic_dword(dev, QPNR)&0x80000000) { + while (rtl92e_readl(dev, QPNR) & 0x80000000) { if (time++ < 100) udelay(10); else break; } - write_nic_dword(dev, QPNR, Data); - while (read_nic_dword(dev, QPNR) & 0x80000000) { + rtl92e_writel(dev, QPNR, Data); + while (rtl92e_readl(dev, QPNR) & 0x80000000) { if (time++ < 100) udelay(10); else return 0; } - return read_nic_dword(dev, RF_DATA); + return rtl92e_readl(dev, RF_DATA); } @@ -317,18 +315,18 @@ static void phy_FwRFSerialWrite(struct net_device *dev, Data |= 0x400000; Data |= 0x80000000; - while (read_nic_dword(dev, QPNR) & 0x80000000) { + while (rtl92e_readl(dev, QPNR) & 0x80000000) { if (time++ < 100) udelay(10); else break; } - write_nic_dword(dev, QPNR, Data); + rtl92e_writel(dev, QPNR, Data); } -void rtl8192_phy_configmac(struct net_device *dev) +void rtl92e_config_mac(struct net_device *dev) { u32 dwArrayLen = 0, i = 0; u32 *pdwArray = NULL; @@ -350,8 +348,8 @@ void rtl8192_phy_configmac(struct net_device *dev) pdwArray[i], pdwArray[i+1], pdwArray[i+2]); if (pdwArray[i] == 0x318) pdwArray[i+2] = 0x00000800; - rtl8192_setBBreg(dev, pdwArray[i], pdwArray[i+1], - pdwArray[i+2]); + rtl92e_set_bb_reg(dev, pdwArray[i], pdwArray[i+1], + pdwArray[i+2]); } return; @@ -377,9 +375,9 @@ static void rtl8192_phyConfigBB(struct net_device *dev, u8 ConfigType) if (ConfigType == BaseBand_Config_PHY_REG) { for (i = 0; i < PHY_REGArrayLen; i += 2) { - rtl8192_setBBreg(dev, Rtl819XPHY_REGArray_Table[i], - bMaskDWord, - Rtl819XPHY_REGArray_Table[i+1]); + rtl92e_set_bb_reg(dev, Rtl819XPHY_REGArray_Table[i], + bMaskDWord, + Rtl819XPHY_REGArray_Table[i+1]); RT_TRACE(COMP_DBG, "i: %x, The Rtl819xUsbPHY_REGArray[0] is %x Rtl819xUsbPHY_REGArray[1] is %x\n", i, Rtl819XPHY_REGArray_Table[i], @@ -387,9 +385,9 @@ static void rtl8192_phyConfigBB(struct net_device *dev, u8 ConfigType) } } else if (ConfigType == BaseBand_Config_AGC_TAB) { for (i = 0; i < AGCTAB_ArrayLen; i += 2) { - rtl8192_setBBreg(dev, Rtl819XAGCTAB_Array_Table[i], - bMaskDWord, - Rtl819XAGCTAB_Array_Table[i+1]); + rtl92e_set_bb_reg(dev, Rtl819XAGCTAB_Array_Table[i], + bMaskDWord, + Rtl819XAGCTAB_Array_Table[i+1]); RT_TRACE(COMP_DBG, "i:%x, The rtl819XAGCTAB_Array[0] is %x rtl819XAGCTAB_Array[1] is %x\n", i, Rtl819XAGCTAB_Array_Table[i], @@ -489,9 +487,8 @@ static void rtl8192_InitBBRFRegDef(struct net_device *dev) } -bool rtl8192_phy_checkBBAndRF(struct net_device *dev, - enum hw90_block CheckBlock, - enum rf90_radio_path eRFPath) +bool rtl92e_check_bb_and_rf(struct net_device *dev, enum hw90_block CheckBlock, + enum rf90_radio_path eRFPath) { bool ret = true; u32 i, CheckTimes = 4, dwRegRead = 0; @@ -515,20 +512,20 @@ bool rtl8192_phy_checkBBAndRF(struct net_device *dev, switch (CheckBlock) { case HW90_BLOCK_PHY0: case HW90_BLOCK_PHY1: - write_nic_dword(dev, WriteAddr[CheckBlock], - WriteData[i]); - dwRegRead = read_nic_dword(dev, WriteAddr[CheckBlock]); + rtl92e_writel(dev, WriteAddr[CheckBlock], + WriteData[i]); + dwRegRead = rtl92e_readl(dev, WriteAddr[CheckBlock]); break; case HW90_BLOCK_RF: WriteData[i] &= 0xfff; - rtl8192_phy_SetRFReg(dev, eRFPath, - WriteAddr[HW90_BLOCK_RF], - bMask12Bits, WriteData[i]); + rtl92e_set_rf_reg(dev, eRFPath, + WriteAddr[HW90_BLOCK_RF], + bMask12Bits, WriteData[i]); mdelay(10); - dwRegRead = rtl8192_phy_QueryRFReg(dev, eRFPath, - WriteAddr[HW90_BLOCK_RF], - bMaskDWord); + dwRegRead = rtl92e_get_rf_reg(dev, eRFPath, + WriteAddr[HW90_BLOCK_RF], + bMaskDWord); mdelay(10); break; @@ -555,29 +552,29 @@ static bool rtl8192_BB_Config_ParaFile(struct net_device *dev) u8 bRegValue = 0, eCheckItem = 0; u32 dwRegValue = 0; - bRegValue = read_nic_byte(dev, BB_GLOBAL_RESET); - write_nic_byte(dev, BB_GLOBAL_RESET, (bRegValue|BB_GLOBAL_RESET_BIT)); + bRegValue = rtl92e_readb(dev, BB_GLOBAL_RESET); + rtl92e_writeb(dev, BB_GLOBAL_RESET, (bRegValue|BB_GLOBAL_RESET_BIT)); - dwRegValue = read_nic_dword(dev, CPU_GEN); - write_nic_dword(dev, CPU_GEN, (dwRegValue&(~CPU_GEN_BB_RST))); + dwRegValue = rtl92e_readl(dev, CPU_GEN); + rtl92e_writel(dev, CPU_GEN, (dwRegValue&(~CPU_GEN_BB_RST))); for (eCheckItem = (enum hw90_block)HW90_BLOCK_PHY0; eCheckItem <= HW90_BLOCK_PHY1; eCheckItem++) { - rtStatus = rtl8192_phy_checkBBAndRF(dev, - (enum hw90_block)eCheckItem, - (enum rf90_radio_path)0); + rtStatus = rtl92e_check_bb_and_rf(dev, + (enum hw90_block)eCheckItem, + (enum rf90_radio_path)0); if (!rtStatus) { RT_TRACE((COMP_ERR | COMP_PHY), - "PHY_RF8256_Config():Check PHY%d Fail!!\n", + "rtl92e_config_rf():Check PHY%d Fail!!\n", eCheckItem-1); return rtStatus; } } - rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn|bOFDMEn, 0x0); + rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bCCKEn|bOFDMEn, 0x0); rtl8192_phyConfigBB(dev, BaseBand_Config_PHY_REG); - dwRegValue = read_nic_dword(dev, CPU_GEN); - write_nic_dword(dev, CPU_GEN, (dwRegValue|CPU_GEN_BB_RST)); + dwRegValue = rtl92e_readl(dev, CPU_GEN); + rtl92e_writel(dev, CPU_GEN, (dwRegValue|CPU_GEN_BB_RST)); rtl8192_phyConfigBB(dev, BaseBand_Config_AGC_TAB); @@ -588,57 +585,57 @@ static bool rtl8192_BB_Config_ParaFile(struct net_device *dev) priv->AntennaTxPwDiff[0]); else dwRegValue = 0x0; - rtl8192_setBBreg(dev, rFPGA0_TxGainStage, - (bXBTxAGC|bXCTxAGC|bXDTxAGC), dwRegValue); + rtl92e_set_bb_reg(dev, rFPGA0_TxGainStage, + (bXBTxAGC|bXCTxAGC|bXDTxAGC), dwRegValue); dwRegValue = priv->CrystalCap; - rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, bXtalCap92x, - dwRegValue); + rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, bXtalCap92x, + dwRegValue); } return rtStatus; } -bool rtl8192_BBConfig(struct net_device *dev) +bool rtl92e_config_bb(struct net_device *dev) { rtl8192_InitBBRFRegDef(dev); return rtl8192_BB_Config_ParaFile(dev); } -void rtl8192_phy_getTxPower(struct net_device *dev) +void rtl92e_get_tx_power(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); priv->MCSTxPowerLevelOriginalOffset[0] = - read_nic_dword(dev, rTxAGC_Rate18_06); + rtl92e_readl(dev, rTxAGC_Rate18_06); priv->MCSTxPowerLevelOriginalOffset[1] = - read_nic_dword(dev, rTxAGC_Rate54_24); + rtl92e_readl(dev, rTxAGC_Rate54_24); priv->MCSTxPowerLevelOriginalOffset[2] = - read_nic_dword(dev, rTxAGC_Mcs03_Mcs00); + rtl92e_readl(dev, rTxAGC_Mcs03_Mcs00); priv->MCSTxPowerLevelOriginalOffset[3] = - read_nic_dword(dev, rTxAGC_Mcs07_Mcs04); + rtl92e_readl(dev, rTxAGC_Mcs07_Mcs04); priv->MCSTxPowerLevelOriginalOffset[4] = - read_nic_dword(dev, rTxAGC_Mcs11_Mcs08); + rtl92e_readl(dev, rTxAGC_Mcs11_Mcs08); priv->MCSTxPowerLevelOriginalOffset[5] = - read_nic_dword(dev, rTxAGC_Mcs15_Mcs12); + rtl92e_readl(dev, rTxAGC_Mcs15_Mcs12); - priv->DefaultInitialGain[0] = read_nic_byte(dev, rOFDM0_XAAGCCore1); - priv->DefaultInitialGain[1] = read_nic_byte(dev, rOFDM0_XBAGCCore1); - priv->DefaultInitialGain[2] = read_nic_byte(dev, rOFDM0_XCAGCCore1); - priv->DefaultInitialGain[3] = read_nic_byte(dev, rOFDM0_XDAGCCore1); + priv->DefaultInitialGain[0] = rtl92e_readb(dev, rOFDM0_XAAGCCore1); + priv->DefaultInitialGain[1] = rtl92e_readb(dev, rOFDM0_XBAGCCore1); + priv->DefaultInitialGain[2] = rtl92e_readb(dev, rOFDM0_XCAGCCore1); + priv->DefaultInitialGain[3] = rtl92e_readb(dev, rOFDM0_XDAGCCore1); RT_TRACE(COMP_INIT, "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x)\n", priv->DefaultInitialGain[0], priv->DefaultInitialGain[1], priv->DefaultInitialGain[2], priv->DefaultInitialGain[3]); - priv->framesync = read_nic_byte(dev, rOFDM0_RxDetector3); - priv->framesyncC34 = read_nic_dword(dev, rOFDM0_RxDetector2); + priv->framesync = rtl92e_readb(dev, rOFDM0_RxDetector3); + priv->framesyncC34 = rtl92e_readl(dev, rOFDM0_RxDetector2); RT_TRACE(COMP_INIT, "Default framesync (0x%x) = 0x%x\n", rOFDM0_RxDetector3, priv->framesync); - priv->SifsTime = read_nic_word(dev, SIFS); + priv->SifsTime = rtl92e_readw(dev, SIFS); } -void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel) +void rtl92e_set_tx_power(struct net_device *dev, u8 channel) { struct r8192_priv *priv = rtllib_priv(dev); u8 powerlevel = 0, powerlevelOFDM24G = 0; @@ -671,16 +668,17 @@ void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel) priv->AntennaTxPwDiff[1]<<4 | priv->AntennaTxPwDiff[0]); - rtl8192_setBBreg(dev, rFPGA0_TxGainStage, - (bXBTxAGC|bXCTxAGC|bXDTxAGC), u4RegValue); + rtl92e_set_bb_reg(dev, rFPGA0_TxGainStage, + (bXBTxAGC|bXCTxAGC|bXDTxAGC), + u4RegValue); } } switch (priv->rf_chip) { case RF_8225: break; case RF_8256: - PHY_SetRF8256CCKTxPower(dev, powerlevel); - PHY_SetRF8256OFDMTxPower(dev, powerlevelOFDM24G); + rtl92e_set_cck_tx_power(dev, powerlevel); + rtl92e_set_ofdm_tx_power(dev, powerlevelOFDM24G); break; case RF_8258: break; @@ -690,7 +688,7 @@ void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel) } } -bool rtl8192_phy_RFConfig(struct net_device *dev) +bool rtl92e_config_phy(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); bool rtStatus = true; @@ -699,7 +697,7 @@ bool rtl8192_phy_RFConfig(struct net_device *dev) case RF_8225: break; case RF_8256: - rtStatus = PHY_RF8256_Config(dev); + rtStatus = rtl92e_config_rf(dev); break; case RF_8258: @@ -714,12 +712,7 @@ bool rtl8192_phy_RFConfig(struct net_device *dev) return rtStatus; } -void rtl8192_phy_updateInitGain(struct net_device *dev) -{ -} - -u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev, - enum rf90_radio_path eRFPath) +u8 rtl92e_config_rf_path(struct net_device *dev, enum rf90_radio_path eRFPath) { int i; @@ -731,10 +724,9 @@ u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev, msleep(100); continue; } - rtl8192_phy_SetRFReg(dev, eRFPath, - Rtl819XRadioA_Array[i], - bMask12Bits, - Rtl819XRadioA_Array[i+1]); + rtl92e_set_rf_reg(dev, eRFPath, Rtl819XRadioA_Array[i], + bMask12Bits, + Rtl819XRadioA_Array[i+1]); } break; @@ -744,10 +736,9 @@ u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev, msleep(100); continue; } - rtl8192_phy_SetRFReg(dev, eRFPath, - Rtl819XRadioB_Array[i], - bMask12Bits, - Rtl819XRadioB_Array[i+1]); + rtl92e_set_rf_reg(dev, eRFPath, Rtl819XRadioB_Array[i], + bMask12Bits, + Rtl819XRadioB_Array[i+1]); } break; @@ -757,10 +748,9 @@ u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev, msleep(100); continue; } - rtl8192_phy_SetRFReg(dev, eRFPath, - Rtl819XRadioC_Array[i], - bMask12Bits, - Rtl819XRadioC_Array[i+1]); + rtl92e_set_rf_reg(dev, eRFPath, Rtl819XRadioC_Array[i], + bMask12Bits, + Rtl819XRadioC_Array[i+1]); } break; @@ -770,9 +760,9 @@ u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev, msleep(100); continue; } - rtl8192_phy_SetRFReg(dev, eRFPath, - Rtl819XRadioD_Array[i], bMask12Bits, - Rtl819XRadioD_Array[i+1]); + rtl92e_set_rf_reg(dev, eRFPath, Rtl819XRadioD_Array[i], + bMask12Bits, + Rtl819XRadioD_Array[i+1]); } break; @@ -794,8 +784,8 @@ static void rtl8192_SetTxPowerLevel(struct net_device *dev, u8 channel) break; case RF_8256: - PHY_SetRF8256CCKTxPower(dev, powerlevel); - PHY_SetRF8256OFDMTxPower(dev, powerlevelOFDM24G); + rtl92e_set_cck_tx_power(dev, powerlevel); + rtl92e_set_ofdm_tx_power(dev, powerlevelOFDM24G); break; case RF_8258: @@ -941,21 +931,21 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel, rtl8192_SetTxPowerLevel(dev, channel); break; case CmdID_WritePortUlong: - write_nic_dword(dev, CurrentCmd->Para1, - CurrentCmd->Para2); + rtl92e_writel(dev, CurrentCmd->Para1, + CurrentCmd->Para2); break; case CmdID_WritePortUshort: - write_nic_word(dev, CurrentCmd->Para1, - (u16)CurrentCmd->Para2); + rtl92e_writew(dev, CurrentCmd->Para1, + (u16)CurrentCmd->Para2); break; case CmdID_WritePortUchar: - write_nic_byte(dev, CurrentCmd->Para1, - (u8)CurrentCmd->Para2); + rtl92e_writeb(dev, CurrentCmd->Para1, + (u8)CurrentCmd->Para2); break; case CmdID_RF_WriteReg: for (eRFPath = 0; eRFPath < priv->NumTotalRFPath; eRFPath++) - rtl8192_phy_SetRFReg(dev, + rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath, CurrentCmd->Para1, bMask12Bits, CurrentCmd->Para2<<7); @@ -1001,7 +991,7 @@ static void rtl8192_SwChnl_WorkItem(struct net_device *dev) RT_TRACE(COMP_TRACE, "<== SwChnlCallback819xUsbWorkItem()\n"); } -u8 rtl8192_phy_SwChnl(struct net_device *dev, u8 channel) +u8 rtl92e_set_channel(struct net_device *dev, u8 channel) { struct r8192_priv *priv = rtllib_priv(dev); @@ -1082,13 +1072,13 @@ static void CCK_Tx_Power_Track_BW_Switch_TSSI(struct net_device *dev) if (priv->rtllib->current_network.channel == 14 && !priv->bcck_in_ch14) { priv->bcck_in_ch14 = true; - dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); } else if (priv->rtllib->current_network.channel != 14 && priv->bcck_in_ch14) { priv->bcck_in_ch14 = false; - dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); } else { - dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); } break; @@ -1110,13 +1100,13 @@ static void CCK_Tx_Power_Track_BW_Switch_TSSI(struct net_device *dev) if (priv->rtllib->current_network.channel == 14 && !priv->bcck_in_ch14) { priv->bcck_in_ch14 = true; - dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); } else if (priv->rtllib->current_network.channel != 14 && priv->bcck_in_ch14) { priv->bcck_in_ch14 = false; - dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); } else { - dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); } break; } @@ -1150,7 +1140,7 @@ static void CCK_Tx_Power_Track_BW_Switch_ThermalMeter(struct net_device *dev) priv->CCK_index); break; } - dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); } static void CCK_Tx_Power_Track_BW_Switch(struct net_device *dev) @@ -1183,17 +1173,17 @@ static void rtl8192_SetBWModeWorkItem(struct net_device *dev) netdev_err(dev, "%s(): Driver is not initialized\n", __func__); return; } - regBwOpMode = read_nic_byte(dev, BW_OPMODE); + regBwOpMode = rtl92e_readb(dev, BW_OPMODE); switch (priv->CurrentChannelBW) { case HT_CHANNEL_WIDTH_20: regBwOpMode |= BW_OPMODE_20MHZ; - write_nic_byte(dev, BW_OPMODE, regBwOpMode); + rtl92e_writeb(dev, BW_OPMODE, regBwOpMode); break; case HT_CHANNEL_WIDTH_20_40: regBwOpMode &= ~BW_OPMODE_20MHZ; - write_nic_byte(dev, BW_OPMODE, regBwOpMode); + rtl92e_writeb(dev, BW_OPMODE, regBwOpMode); break; default: @@ -1204,38 +1194,38 @@ static void rtl8192_SetBWModeWorkItem(struct net_device *dev) switch (priv->CurrentChannelBW) { case HT_CHANNEL_WIDTH_20: - rtl8192_setBBreg(dev, rFPGA0_RFMOD, bRFMOD, 0x0); - rtl8192_setBBreg(dev, rFPGA1_RFMOD, bRFMOD, 0x0); + rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bRFMOD, 0x0); + rtl92e_set_bb_reg(dev, rFPGA1_RFMOD, bRFMOD, 0x0); if (!priv->btxpower_tracking) { - write_nic_dword(dev, rCCK0_TxFilter1, 0x1a1b0000); - write_nic_dword(dev, rCCK0_TxFilter2, 0x090e1317); - write_nic_dword(dev, rCCK0_DebugPort, 0x00000204); + rtl92e_writel(dev, rCCK0_TxFilter1, 0x1a1b0000); + rtl92e_writel(dev, rCCK0_TxFilter2, 0x090e1317); + rtl92e_writel(dev, rCCK0_DebugPort, 0x00000204); } else { CCK_Tx_Power_Track_BW_Switch(dev); } - rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x00100000, 1); + rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x00100000, 1); break; case HT_CHANNEL_WIDTH_20_40: - rtl8192_setBBreg(dev, rFPGA0_RFMOD, bRFMOD, 0x1); - rtl8192_setBBreg(dev, rFPGA1_RFMOD, bRFMOD, 0x1); + rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bRFMOD, 0x1); + rtl92e_set_bb_reg(dev, rFPGA1_RFMOD, bRFMOD, 0x1); if (!priv->btxpower_tracking) { - write_nic_dword(dev, rCCK0_TxFilter1, 0x35360000); - write_nic_dword(dev, rCCK0_TxFilter2, 0x121c252e); - write_nic_dword(dev, rCCK0_DebugPort, 0x00000409); + rtl92e_writel(dev, rCCK0_TxFilter1, 0x35360000); + rtl92e_writel(dev, rCCK0_TxFilter2, 0x121c252e); + rtl92e_writel(dev, rCCK0_DebugPort, 0x00000409); } else { CCK_Tx_Power_Track_BW_Switch(dev); } - rtl8192_setBBreg(dev, rCCK0_System, bCCKSideBand, - (priv->nCur40MhzPrimeSC>>1)); - rtl8192_setBBreg(dev, rOFDM1_LSTF, 0xC00, - priv->nCur40MhzPrimeSC); + rtl92e_set_bb_reg(dev, rCCK0_System, bCCKSideBand, + (priv->nCur40MhzPrimeSC>>1)); + rtl92e_set_bb_reg(dev, rOFDM1_LSTF, 0xC00, + priv->nCur40MhzPrimeSC); - rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x00100000, 0); + rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x00100000, 0); break; default: netdev_err(dev, "%s(): unknown Bandwidth: %#X\n", __func__, @@ -1249,7 +1239,7 @@ static void rtl8192_SetBWModeWorkItem(struct net_device *dev) break; case RF_8256: - PHY_SetRF8256Bandwidth(dev, priv->CurrentChannelBW); + rtl92e_set_bandwidth(dev, priv->CurrentChannelBW); break; case RF_8258: @@ -1270,8 +1260,8 @@ static void rtl8192_SetBWModeWorkItem(struct net_device *dev) RT_TRACE(COMP_SWBW, "<==SetBWMode819xUsb()"); } -void rtl8192_SetBWMode(struct net_device *dev, enum ht_channel_width Bandwidth, - enum ht_extchnl_offset Offset) +void rtl92e_set_bw_mode(struct net_device *dev, enum ht_channel_width Bandwidth, + enum ht_extchnl_offset Offset) { struct r8192_priv *priv = rtllib_priv(dev); @@ -1295,7 +1285,7 @@ void rtl8192_SetBWMode(struct net_device *dev, enum ht_channel_width Bandwidth, } -void InitialGain819xPci(struct net_device *dev, u8 Operation) +void rtl92e_init_gain(struct net_device *dev, u8 Operation) { #define SCAN_RX_INITIAL_GAIN 0x17 #define POWER_DETECTION_TH 0x08 @@ -1312,21 +1302,21 @@ void InitialGain819xPci(struct net_device *dev, u8 Operation) BitMask = bMaskByte0; if (dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM) - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); + rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x8); priv->initgain_backup.xaagccore1 = - (u8)rtl8192_QueryBBReg(dev, rOFDM0_XAAGCCore1, - BitMask); + (u8)rtl92e_get_bb_reg(dev, rOFDM0_XAAGCCore1, + BitMask); priv->initgain_backup.xbagccore1 = - (u8)rtl8192_QueryBBReg(dev, rOFDM0_XBAGCCore1, - BitMask); + (u8)rtl92e_get_bb_reg(dev, rOFDM0_XBAGCCore1, + BitMask); priv->initgain_backup.xcagccore1 = - (u8)rtl8192_QueryBBReg(dev, rOFDM0_XCAGCCore1, - BitMask); + (u8)rtl92e_get_bb_reg(dev, rOFDM0_XCAGCCore1, + BitMask); priv->initgain_backup.xdagccore1 = - (u8)rtl8192_QueryBBReg(dev, rOFDM0_XDAGCCore1, - BitMask); + (u8)rtl92e_get_bb_reg(dev, rOFDM0_XDAGCCore1, + BitMask); BitMask = bMaskByte2; - priv->initgain_backup.cca = (u8)rtl8192_QueryBBReg(dev, + priv->initgain_backup.cca = (u8)rtl92e_get_bb_reg(dev, rCCK0_CCA, BitMask); RT_TRACE(COMP_SCAN, @@ -1347,13 +1337,13 @@ void InitialGain819xPci(struct net_device *dev, u8 Operation) RT_TRACE(COMP_SCAN, "Write scan initial gain = 0x%x\n", initial_gain); - write_nic_byte(dev, rOFDM0_XAAGCCore1, initial_gain); - write_nic_byte(dev, rOFDM0_XBAGCCore1, initial_gain); - write_nic_byte(dev, rOFDM0_XCAGCCore1, initial_gain); - write_nic_byte(dev, rOFDM0_XDAGCCore1, initial_gain); + rtl92e_writeb(dev, rOFDM0_XAAGCCore1, initial_gain); + rtl92e_writeb(dev, rOFDM0_XBAGCCore1, initial_gain); + rtl92e_writeb(dev, rOFDM0_XCAGCCore1, initial_gain); + rtl92e_writeb(dev, rOFDM0_XDAGCCore1, initial_gain); RT_TRACE(COMP_SCAN, "Write scan 0xa0a = 0x%x\n", POWER_DETECTION_TH); - write_nic_byte(dev, 0xa0a, POWER_DETECTION_TH); + rtl92e_writeb(dev, 0xa0a, POWER_DETECTION_TH); break; case IG_Restore: RT_TRACE(COMP_SCAN, @@ -1361,18 +1351,18 @@ void InitialGain819xPci(struct net_device *dev, u8 Operation) BitMask = 0x7f; if (dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM) - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); + rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x8); - rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, BitMask, + rtl92e_set_bb_reg(dev, rOFDM0_XAAGCCore1, BitMask, (u32)priv->initgain_backup.xaagccore1); - rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, BitMask, + rtl92e_set_bb_reg(dev, rOFDM0_XBAGCCore1, BitMask, (u32)priv->initgain_backup.xbagccore1); - rtl8192_setBBreg(dev, rOFDM0_XCAGCCore1, BitMask, + rtl92e_set_bb_reg(dev, rOFDM0_XCAGCCore1, BitMask, (u32)priv->initgain_backup.xcagccore1); - rtl8192_setBBreg(dev, rOFDM0_XDAGCCore1, BitMask, + rtl92e_set_bb_reg(dev, rOFDM0_XDAGCCore1, BitMask, (u32)priv->initgain_backup.xdagccore1); BitMask = bMaskByte2; - rtl8192_setBBreg(dev, rCCK0_CCA, BitMask, + rtl92e_set_bb_reg(dev, rCCK0_CCA, BitMask, (u32)priv->initgain_backup.cca); RT_TRACE(COMP_SCAN, @@ -1391,12 +1381,12 @@ void InitialGain819xPci(struct net_device *dev, u8 Operation) "Scan BBInitialGainRestore 0xa0a is %x\n", priv->initgain_backup.cca); - rtl8192_phy_setTxPower(dev, + rtl92e_set_tx_power(dev, priv->rtllib->current_network.channel); if (dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM) - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); + rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x1); break; default: RT_TRACE(COMP_SCAN, "Unknown IG Operation.\n"); @@ -1405,17 +1395,17 @@ void InitialGain819xPci(struct net_device *dev, u8 Operation) } } -void PHY_SetRtl8192eRfOff(struct net_device *dev) +void rtl92e_set_rf_off(struct net_device *dev) { - rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0); - rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x0); - rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x18, 0x0); - rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0xf, 0x0); - rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0xf, 0x0); - rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x0); - rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x4, 0x0); - write_nic_byte(dev, ANAPAR_FOR_8192PciE, 0x07); + rtl92e_set_bb_reg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0); + rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0x300, 0x0); + rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x18, 0x0); + rtl92e_set_bb_reg(dev, rOFDM0_TRxPathEnable, 0xf, 0x0); + rtl92e_set_bb_reg(dev, rOFDM1_TRxPathEnable, 0xf, 0x0); + rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x60, 0x0); + rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x4, 0x0); + rtl92e_writeb(dev, ANAPAR_FOR_8192PciE, 0x07); } @@ -1447,7 +1437,7 @@ static bool SetRFPowerState8190(struct net_device *dev, do { InitilizeCount--; priv->RegRfOff = false; - rtstatus = NicIFEnableNIC(dev); + rtstatus = rtl92e_enable_nic(dev); } while (!rtstatus && (InitilizeCount > 0)); if (!rtstatus) { @@ -1461,24 +1451,24 @@ static bool SetRFPowerState8190(struct net_device *dev, RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC); } else { - write_nic_byte(dev, ANAPAR, 0x37); + rtl92e_writeb(dev, ANAPAR, 0x37); mdelay(1); - rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, + rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x4, 0x1); priv->bHwRfOffAction = 0; - rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, - BIT4, 0x1); - rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, - 0x300, 0x3); - rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, - 0x18, 0x3); - rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x3, - 0x3); - rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x3, - 0x3); - rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, - 0x60, 0x3); + rtl92e_set_bb_reg(dev, rFPGA0_XA_RFInterfaceOE, + BIT4, 0x1); + rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, + 0x300, 0x3); + rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, + 0x18, 0x3); + rtl92e_set_bb_reg(dev, rOFDM0_TRxPathEnable, + 0x3, 0x3); + rtl92e_set_bb_reg(dev, rOFDM1_TRxPathEnable, + 0x3, 0x3); + rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, + 0x60, 0x3); } @@ -1511,7 +1501,7 @@ static bool SetRFPowerState8190(struct net_device *dev, break; } } - PHY_SetRtl8192eRfOff(dev); + rtl92e_set_rf_off(dev); break; case eRfOff: @@ -1543,11 +1533,11 @@ static bool SetRFPowerState8190(struct net_device *dev, if (pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC && !RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC)) { - NicIFDisableNIC(dev); + rtl92e_disable_nic(dev); RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC); } else if (!(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC)) { - PHY_SetRtl8192eRfOff(dev); + rtl92e_set_rf_off(dev); } break; @@ -1586,32 +1576,34 @@ static bool SetRFPowerState8190(struct net_device *dev, return bResult; } -bool SetRFPowerState(struct net_device *dev, - enum rt_rf_power_state eRFPowerState) +bool rtl92e_set_rf_power_state(struct net_device *dev, + enum rt_rf_power_state eRFPowerState) { struct r8192_priv *priv = rtllib_priv(dev); bool bResult = false; - RT_TRACE(COMP_PS, "---------> SetRFPowerState(): eRFPowerState(%d)\n", + RT_TRACE(COMP_PS, + "---------> rtl92e_set_rf_power_state(): eRFPowerState(%d)\n", eRFPowerState); if (eRFPowerState == priv->rtllib->eRFPowerState && priv->bHwRfOffAction == 0) { RT_TRACE(COMP_PS, - "<--------- SetRFPowerState(): discard the request for eRFPowerState(%d) is the same.\n", + "<--------- rtl92e_set_rf_power_state(): discard the request for eRFPowerState(%d) is the same.\n", eRFPowerState); return bResult; } bResult = SetRFPowerState8190(dev, eRFPowerState); - RT_TRACE(COMP_PS, "<--------- SetRFPowerState(): bResult(%d)\n", + RT_TRACE(COMP_PS, + "<--------- rtl92e_set_rf_power_state(): bResult(%d)\n", bResult); return bResult; } -void PHY_ScanOperationBackup8192(struct net_device *dev, u8 Operation) +void rtl92e_scan_op_backup(struct net_device *dev, u8 Operation) { struct r8192_priv *priv = rtllib_priv(dev); diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.h index ef85587c6a12..350d3063df72 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.h +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.h @@ -67,45 +67,40 @@ enum rf90_radio_path { #define bMaskLWord 0x0000ffff #define bMaskDWord 0xffffffff -extern u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device *dev, - u32 eRFPath); -extern void rtl8192_setBBreg(struct net_device *dev, u32 dwRegAddr, - u32 dwBitMask, u32 dwData); -extern u32 rtl8192_QueryBBReg(struct net_device *dev, u32 dwRegAddr, - u32 dwBitMask); -extern void rtl8192_phy_SetRFReg(struct net_device *dev, - enum rf90_radio_path eRFPath, - u32 RegAddr, u32 BitMask, u32 Data); -extern u32 rtl8192_phy_QueryRFReg(struct net_device *dev, - enum rf90_radio_path eRFPath, - u32 RegAddr, u32 BitMask); -extern void rtl8192_phy_configmac(struct net_device *dev); -extern bool rtl8192_phy_checkBBAndRF(struct net_device *dev, - enum hw90_block CheckBlock, - enum rf90_radio_path eRFPath); -extern bool rtl8192_BBConfig(struct net_device *dev); -extern void rtl8192_phy_getTxPower(struct net_device *dev); -extern void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel); -extern bool rtl8192_phy_RFConfig(struct net_device *dev); -extern void rtl8192_phy_updateInitGain(struct net_device *dev); -extern u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev, - enum rf90_radio_path eRFPath); +extern u8 rtl92e_is_legal_rf_path(struct net_device *dev, u32 eRFPath); +extern void rtl92e_set_bb_reg(struct net_device *dev, u32 dwRegAddr, + u32 dwBitMask, u32 dwData); +extern u32 rtl92e_get_bb_reg(struct net_device *dev, u32 dwRegAddr, + u32 dwBitMask); +extern void rtl92e_set_rf_reg(struct net_device *dev, + enum rf90_radio_path eRFPath, u32 RegAddr, + u32 BitMask, u32 Data); +extern u32 rtl92e_get_rf_reg(struct net_device *dev, + enum rf90_radio_path eRFPath, u32 RegAddr, + u32 BitMask); +extern void rtl92e_config_mac(struct net_device *dev); +extern bool rtl92e_check_bb_and_rf(struct net_device *dev, + enum hw90_block CheckBlock, + enum rf90_radio_path eRFPath); +extern bool rtl92e_config_bb(struct net_device *dev); +extern void rtl92e_get_tx_power(struct net_device *dev); +extern void rtl92e_set_tx_power(struct net_device *dev, u8 channel); +extern bool rtl92e_config_phy(struct net_device *dev); +extern u8 rtl92e_config_rf_path(struct net_device *dev, + enum rf90_radio_path eRFPath); -extern u8 rtl8192_phy_SwChnl(struct net_device *dev, u8 channel); -extern void rtl8192_SetBWMode(struct net_device *dev, - enum ht_channel_width Bandwidth, - enum ht_extchnl_offset Offset); -extern void InitialGain819xPci(struct net_device *dev, u8 Operation); +extern u8 rtl92e_set_channel(struct net_device *dev, u8 channel); +extern void rtl92e_set_bw_mode(struct net_device *dev, + enum ht_channel_width Bandwidth, + enum ht_extchnl_offset Offset); +extern void rtl92e_init_gain(struct net_device *dev, u8 Operation); -extern void PHY_SetRtl8192eRfOff(struct net_device *dev); +extern void rtl92e_set_rf_off(struct net_device *dev); -bool -SetRFPowerState( - struct net_device *dev, - enum rt_rf_power_state eRFPowerState - ); -#define PHY_SetRFPowerState SetRFPowerState +bool rtl92e_set_rf_power_state(struct net_device *dev, + enum rt_rf_power_state eRFPowerState); +#define PHY_SetRFPowerState rtl92e_set_rf_power_state -extern void PHY_ScanOperationBackup8192(struct net_device *dev, u8 Operation); +extern void rtl92e_scan_op_backup(struct net_device *dev, u8 Operation); #endif diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c index f246222e5fc9..29dd93ac5e93 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c @@ -28,15 +28,15 @@ #include "r8190P_rtl8256.h" /* RTL8225 Radio frontend */ #include "r8192E_cmdpkt.h" -void CamResetAllEntry(struct net_device *dev) +void rtl92e_cam_reset(struct net_device *dev) { u32 ulcommand = 0; ulcommand |= BIT31|BIT30; - write_nic_dword(dev, RWCAM, ulcommand); + rtl92e_writel(dev, RWCAM, ulcommand); } -void EnableHWSecurityConfig8192(struct net_device *dev) +void rtl92e_enable_hw_security_config(struct net_device *dev) { u8 SECR_value = 0x0; struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); @@ -65,11 +65,12 @@ void EnableHWSecurityConfig8192(struct net_device *dev) RT_TRACE(COMP_SEC, "%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n", __func__, ieee->hwsec_active, ieee->pairwise_key_type, SECR_value); - write_nic_byte(dev, SECR, SECR_value); + rtl92e_writeb(dev, SECR, SECR_value); } -void set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, - const u8 *MacAddr, u8 DefaultKey, u32 *KeyContent, u8 is_mesh) +void rtl92e_set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, + u16 KeyType, const u8 *MacAddr, u8 DefaultKey, + u32 *KeyContent, u8 is_mesh) { struct r8192_priv *priv = rtllib_priv(dev); struct rtllib_device *ieee = priv->rtllib; @@ -77,6 +78,10 @@ void set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, RT_TRACE(COMP_DBG, "===========>%s():EntryNo is %d,KeyIndex is %d,KeyType is %d,is_mesh is %d\n", __func__, EntryNo, KeyIndex, KeyType, is_mesh); + + if (EntryNo >= TOTAL_CAM_ENTRY) + return; + if (!is_mesh) { ieee->swcamtable[EntryNo].bused = true; ieee->swcamtable[EntryNo].key_index = KeyIndex; @@ -87,8 +92,9 @@ void set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, } } -void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, - const u8 *MacAddr, u8 DefaultKey, u32 *KeyContent) +void rtl92e_set_key(struct net_device *dev, u8 EntryNo, u8 KeyIndex, + u16 KeyType, const u8 *MacAddr, u8 DefaultKey, + u32 *KeyContent) { u32 TargetCommand = 0; u32 TargetContent = 0; @@ -106,16 +112,18 @@ void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, return; } down(&priv->rtllib->ips_sem); - IPSLeave(dev); + rtl92e_ips_leave(dev); up(&priv->rtllib->ips_sem); } } priv->rtllib->is_set_key = true; - if (EntryNo >= TOTAL_CAM_ENTRY) + if (EntryNo >= TOTAL_CAM_ENTRY) { netdev_info(dev, "%s(): Invalid CAM entry\n", __func__); + return; + } RT_TRACE(COMP_SEC, - "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d,KeyType:%d, MacAddr %pM\n", + "====>to rtl92e_set_key(), dev:%p, EntryNo:%d, KeyIndex:%d,KeyType:%d, MacAddr %pM\n", dev, EntryNo, KeyIndex, KeyType, MacAddr); if (DefaultKey) @@ -133,20 +141,20 @@ void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, (u32)(*(MacAddr+1)) << 24 | (u32)usConfig; - write_nic_dword(dev, WCAMI, TargetContent); - write_nic_dword(dev, RWCAM, TargetCommand); + rtl92e_writel(dev, WCAMI, TargetContent); + rtl92e_writel(dev, RWCAM, TargetCommand); } else if (i == 1) { TargetContent = (u32)(*(MacAddr+2)) | (u32)(*(MacAddr+3)) << 8 | (u32)(*(MacAddr+4)) << 16 | (u32)(*(MacAddr+5)) << 24; - write_nic_dword(dev, WCAMI, TargetContent); - write_nic_dword(dev, RWCAM, TargetCommand); + rtl92e_writel(dev, WCAMI, TargetContent); + rtl92e_writel(dev, RWCAM, TargetCommand); } else { if (KeyContent != NULL) { - write_nic_dword(dev, WCAMI, - (u32)(*(KeyContent+i-2))); - write_nic_dword(dev, RWCAM, TargetCommand); + rtl92e_writel(dev, WCAMI, + (u32)(*(KeyContent+i-2))); + rtl92e_writel(dev, RWCAM, TargetCommand); udelay(100); } } @@ -154,7 +162,7 @@ void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, RT_TRACE(COMP_SEC, "=========>after set key, usconfig:%x\n", usConfig); } -void CamRestoreAllEntry(struct net_device *dev) +void rtl92e_cam_restore(struct net_device *dev) { u8 EntryId = 0; struct r8192_priv *priv = rtllib_priv(dev); @@ -170,7 +178,7 @@ void CamRestoreAllEntry(struct net_device *dev) 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - RT_TRACE(COMP_SEC, "CamRestoreAllEntry:\n"); + RT_TRACE(COMP_SEC, "rtl92e_cam_restore:\n"); if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40) || @@ -179,36 +187,41 @@ void CamRestoreAllEntry(struct net_device *dev) for (EntryId = 0; EntryId < 4; EntryId++) { MacAddr = CAM_CONST_ADDR[EntryId]; if (priv->rtllib->swcamtable[EntryId].bused) { - setKey(dev, EntryId, EntryId, - priv->rtllib->pairwise_key_type, MacAddr, - 0, (u32 *)(&priv->rtllib->swcamtable - [EntryId].key_buf[0])); + rtl92e_set_key(dev, EntryId, EntryId, + priv->rtllib->pairwise_key_type, + MacAddr, 0, + (u32 *)(&priv->rtllib->swcamtable + [EntryId].key_buf[0])); } } } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_TKIP) { if (priv->rtllib->iw_mode == IW_MODE_ADHOC) { - setKey(dev, 4, 0, priv->rtllib->pairwise_key_type, - (u8 *)dev->dev_addr, 0, - (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0])); + rtl92e_set_key(dev, 4, 0, + priv->rtllib->pairwise_key_type, + (u8 *)dev->dev_addr, 0, + (u32 *)(&priv->rtllib->swcamtable[4]. + key_buf[0])); } else { - setKey(dev, 4, 0, priv->rtllib->pairwise_key_type, - MacAddr, 0, - (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0])); + rtl92e_set_key(dev, 4, 0, + priv->rtllib->pairwise_key_type, + MacAddr, 0, + (u32 *)(&priv->rtllib->swcamtable[4]. + key_buf[0])); } } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_CCMP) { if (priv->rtllib->iw_mode == IW_MODE_ADHOC) { - setKey(dev, 4, 0, - priv->rtllib->pairwise_key_type, - (u8 *)dev->dev_addr, 0, - (u32 *)(&priv->rtllib->swcamtable[4]. - key_buf[0])); + rtl92e_set_key(dev, 4, 0, + priv->rtllib->pairwise_key_type, + (u8 *)dev->dev_addr, 0, + (u32 *)(&priv->rtllib->swcamtable[4]. + key_buf[0])); } else { - setKey(dev, 4, 0, - priv->rtllib->pairwise_key_type, MacAddr, - 0, (u32 *)(&priv->rtllib->swcamtable[4]. - key_buf[0])); + rtl92e_set_key(dev, 4, 0, + priv->rtllib->pairwise_key_type, MacAddr, + 0, (u32 *)(&priv->rtllib->swcamtable[4]. + key_buf[0])); } } @@ -216,20 +229,18 @@ void CamRestoreAllEntry(struct net_device *dev) MacAddr = CAM_CONST_BROAD; for (EntryId = 1; EntryId < 4; EntryId++) { if (priv->rtllib->swcamtable[EntryId].bused) { - setKey(dev, EntryId, EntryId, - priv->rtllib->group_key_type, - MacAddr, 0, - (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]) - ); + rtl92e_set_key(dev, EntryId, EntryId, + priv->rtllib->group_key_type, + MacAddr, 0, + (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0])); } } if (priv->rtllib->iw_mode == IW_MODE_ADHOC) { if (priv->rtllib->swcamtable[0].bused) { - setKey(dev, 0, 0, - priv->rtllib->group_key_type, - CAM_CONST_ADDR[0], 0, - (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]) - ); + rtl92e_set_key(dev, 0, 0, + priv->rtllib->group_key_type, + CAM_CONST_ADDR[0], 0, + (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0])); } else { netdev_warn(dev, "%s(): ADHOC TKIP: missing key entry.\n", @@ -241,19 +252,19 @@ void CamRestoreAllEntry(struct net_device *dev) MacAddr = CAM_CONST_BROAD; for (EntryId = 1; EntryId < 4; EntryId++) { if (priv->rtllib->swcamtable[EntryId].bused) { - setKey(dev, EntryId, EntryId, - priv->rtllib->group_key_type, - MacAddr, 0, - (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0])); + rtl92e_set_key(dev, EntryId, EntryId, + priv->rtllib->group_key_type, + MacAddr, 0, + (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0])); } } if (priv->rtllib->iw_mode == IW_MODE_ADHOC) { if (priv->rtllib->swcamtable[0].bused) { - setKey(dev, 0, 0, - priv->rtllib->group_key_type, - CAM_CONST_ADDR[0], 0, - (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0])); + rtl92e_set_key(dev, 0, 0, + priv->rtllib->group_key_type, + CAM_CONST_ADDR[0], 0, + (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0])); } else { netdev_warn(dev, "%s(): ADHOC CCMP: missing key entry.\n", diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h index f23ab46c77e7..9ef8b36fc6b5 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h @@ -28,12 +28,14 @@ #include <linux/types.h> struct net_device; -void CamResetAllEntry(struct net_device *dev); -void EnableHWSecurityConfig8192(struct net_device *dev); -void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, - const u8 *MacAddr, u8 DefaultKey, u32 *KeyContent); -void set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, - const u8 *MacAddr, u8 DefaultKey, u32 *KeyContent, u8 is_mesh); -void CamRestoreAllEntry(struct net_device *dev); +void rtl92e_cam_reset(struct net_device *dev); +void rtl92e_enable_hw_security_config(struct net_device *dev); +void rtl92e_set_key(struct net_device *dev, u8 EntryNo, u8 KeyIndex, + u16 KeyType, const u8 *MacAddr, u8 DefaultKey, + u32 *KeyContent); +void rtl92e_set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, + u16 KeyType, const u8 *MacAddr, u8 DefaultKey, + u32 *KeyContent, u8 is_mesh); +void rtl92e_cam_restore(struct net_device *dev); #endif diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index ca8406bba26d..c868cb373a4b 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -44,24 +44,24 @@ static char *ifname = "wlan%d"; static struct rtl819x_ops rtl819xp_ops = { .nic_type = NIC_8192E, - .get_eeprom_size = rtl8192_get_eeprom_size, - .init_adapter_variable = rtl8192_InitializeVariables, - .initialize_adapter = rtl8192_adapter_start, - .link_change = rtl8192_link_change, - .tx_fill_descriptor = rtl8192_tx_fill_desc, - .tx_fill_cmd_descriptor = rtl8192_tx_fill_cmd_desc, - .rx_query_status_descriptor = rtl8192_rx_query_status_desc, + .get_eeprom_size = rtl92e_get_eeprom_size, + .init_adapter_variable = rtl92e_init_variables, + .initialize_adapter = rtl92e_start_adapter, + .link_change = rtl92e_link_change, + .tx_fill_descriptor = rtl92e_fill_tx_desc, + .tx_fill_cmd_descriptor = rtl92e_fill_tx_cmd_desc, + .rx_query_status_descriptor = rtl92e_get_rx_stats, .rx_command_packet_handler = NULL, - .stop_adapter = rtl8192_halt_adapter, - .update_ratr_table = rtl8192_update_ratr_table, - .irq_enable = rtl8192_EnableInterrupt, - .irq_disable = rtl8192_DisableInterrupt, - .irq_clear = rtl8192_ClearInterrupt, - .rx_enable = rtl8192_enable_rx, - .tx_enable = rtl8192_enable_tx, - .interrupt_recognized = rtl8192_interrupt_recognized, - .TxCheckStuckHandler = rtl8192_HalTxCheckStuck, - .RxCheckStuckHandler = rtl8192_HalRxCheckStuck, + .stop_adapter = rtl92e_stop_adapter, + .update_ratr_table = rtl92e_update_ratr_table, + .irq_enable = rtl92e_enable_irq, + .irq_disable = rtl92e_disable_irq, + .irq_clear = rtl92e_clear_irq, + .rx_enable = rtl92e_enable_rx, + .tx_enable = rtl92e_enable_tx, + .interrupt_recognized = rtl92e_ack_irq, + .TxCheckStuckHandler = rtl92e_is_tx_stuck, + .RxCheckStuckHandler = rtl92e_is_rx_stuck, }; static struct pci_device_id rtl8192_pci_id_tbl[] = { @@ -83,15 +83,13 @@ static struct pci_driver rtl8192_pci_driver = { .id_table = rtl8192_pci_id_tbl, /* PCI_ID table */ .probe = rtl8192_pci_probe, /* probe fn */ .remove = rtl8192_pci_disconnect, /* remove fn */ - .suspend = rtl8192E_suspend, /* PM suspend fn */ - .resume = rtl8192E_resume, /* PM resume fn */ + .suspend = rtl92e_suspend, /* PM suspend fn */ + .resume = rtl92e_resume, /* PM resume fn */ }; static short rtl8192_is_tx_queue_empty(struct net_device *dev); static void rtl819x_watchdog_wqcallback(void *data); static void watch_dog_timer_callback(unsigned long data); -static void rtl8192_data_hard_stop(struct net_device *dev); -static void rtl8192_data_hard_resume(struct net_device *dev); static void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int rate); static int rtl8192_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); @@ -110,36 +108,36 @@ static void rtl8192_restart(void *data); -----------------------------IO STUFF------------------------- *****************************************************************************/ -u8 read_nic_byte(struct net_device *dev, int x) +u8 rtl92e_readb(struct net_device *dev, int x) { return 0xff & readb((u8 __iomem *)dev->mem_start + x); } -u32 read_nic_dword(struct net_device *dev, int x) +u32 rtl92e_readl(struct net_device *dev, int x) { return readl((u8 __iomem *)dev->mem_start + x); } -u16 read_nic_word(struct net_device *dev, int x) +u16 rtl92e_readw(struct net_device *dev, int x) { return readw((u8 __iomem *)dev->mem_start + x); } -void write_nic_byte(struct net_device *dev, int x, u8 y) +void rtl92e_writeb(struct net_device *dev, int x, u8 y) { writeb(y, (u8 __iomem *)dev->mem_start + x); udelay(20); } -void write_nic_dword(struct net_device *dev, int x, u32 y) +void rtl92e_writel(struct net_device *dev, int x, u32 y) { writel(y, (u8 __iomem *)dev->mem_start + x); udelay(20); } -void write_nic_word(struct net_device *dev, int x, u16 y) +void rtl92e_writew(struct net_device *dev, int x, u16 y) { writew(y, (u8 __iomem *)dev->mem_start + x); @@ -149,10 +147,9 @@ void write_nic_word(struct net_device *dev, int x, u16 y) /**************************************************************************** -----------------------------GENERAL FUNCTION------------------------- *****************************************************************************/ -bool MgntActSet_RF_State(struct net_device *dev, +bool rtl92e_set_rf_state(struct net_device *dev, enum rt_rf_power_state StateToSet, - RT_RF_CHANGE_SOURCE ChangeSource, - bool ProtectOrNot) + RT_RF_CHANGE_SOURCE ChangeSource) { struct r8192_priv *priv = rtllib_priv(dev); struct rtllib_device *ieee = priv->rtllib; @@ -163,39 +160,34 @@ bool MgntActSet_RF_State(struct net_device *dev, unsigned long flag; RT_TRACE((COMP_PS | COMP_RF), - "===>MgntActSet_RF_State(): StateToSet(%d)\n", StateToSet); - - ProtectOrNot = false; + "===>rtl92e_set_rf_state(): StateToSet(%d)\n", StateToSet); + while (true) { + spin_lock_irqsave(&priv->rf_ps_lock, flag); + if (priv->RFChangeInProgress) { + spin_unlock_irqrestore(&priv->rf_ps_lock, flag); + RT_TRACE((COMP_PS | COMP_RF), + "rtl92e_set_rf_state(): RF Change in progress! Wait to set..StateToSet(%d).\n", + StateToSet); - if (!ProtectOrNot) { - while (true) { - spin_lock_irqsave(&priv->rf_ps_lock, flag); - if (priv->RFChangeInProgress) { - spin_unlock_irqrestore(&priv->rf_ps_lock, flag); + while (priv->RFChangeInProgress) { + RFWaitCounter++; RT_TRACE((COMP_PS | COMP_RF), - "MgntActSet_RF_State(): RF Change in progress! Wait to set..StateToSet(%d).\n", - StateToSet); - - while (priv->RFChangeInProgress) { - RFWaitCounter++; - RT_TRACE((COMP_PS | COMP_RF), - "MgntActSet_RF_State(): Wait 1 ms (%d times)...\n", - RFWaitCounter); - mdelay(1); - - if (RFWaitCounter > 100) { - netdev_warn(dev, - "%s(): Timeout waiting for RF change.\n", - __func__); - return false; - } + "rtl92e_set_rf_state(): Wait 1 ms (%d times)...\n", + RFWaitCounter); + mdelay(1); + + if (RFWaitCounter > 100) { + netdev_warn(dev, + "%s(): Timeout waiting for RF change.\n", + __func__); + return false; } - } else { - priv->RFChangeInProgress = true; - spin_unlock_irqrestore(&priv->rf_ps_lock, flag); - break; } + } else { + priv->RFChangeInProgress = true; + spin_unlock_irqrestore(&priv->rf_ps_lock, flag); + break; } } @@ -218,7 +210,7 @@ bool MgntActSet_RF_State(struct net_device *dev, bConnectBySSID = true; } else { RT_TRACE((COMP_PS | COMP_RF), - "MgntActSet_RF_State - eRfon reject pMgntInfo->RfOffReason= 0x%x, ChangeSource=0x%X\n", + "rtl92e_set_rf_state - eRfon reject pMgntInfo->RfOffReason= 0x%x, ChangeSource=0x%X\n", priv->rtllib->RfOffReason, ChangeSource); } @@ -255,7 +247,7 @@ bool MgntActSet_RF_State(struct net_device *dev, if (bActionAllowed) { RT_TRACE((COMP_PS | COMP_RF), - "MgntActSet_RF_State(): Action is allowed.... StateToSet(%d), RfOffReason(%#X)\n", + "rtl92e_set_rf_state(): Action is allowed.... StateToSet(%d), RfOffReason(%#X)\n", StateToSet, priv->rtllib->RfOffReason); PHY_SetRFPowerState(dev, StateToSet); if (StateToSet == eRfOn) { @@ -268,17 +260,15 @@ bool MgntActSet_RF_State(struct net_device *dev, } } else { RT_TRACE((COMP_PS | COMP_RF), - "MgntActSet_RF_State(): Action is rejected.... StateToSet(%d), ChangeSource(%#X), RfOffReason(%#X)\n", + "rtl92e_set_rf_state(): Action is rejected.... StateToSet(%d), ChangeSource(%#X), RfOffReason(%#X)\n", StateToSet, ChangeSource, priv->rtllib->RfOffReason); } - if (!ProtectOrNot) { - spin_lock_irqsave(&priv->rf_ps_lock, flag); - priv->RFChangeInProgress = false; - spin_unlock_irqrestore(&priv->rf_ps_lock, flag); - } + spin_lock_irqsave(&priv->rf_ps_lock, flag); + priv->RFChangeInProgress = false; + spin_unlock_irqrestore(&priv->rf_ps_lock, flag); - RT_TRACE((COMP_PS | COMP_RF), "<===MgntActSet_RF_State()\n"); + RT_TRACE((COMP_PS | COMP_RF), "<===rtl92e_set_rf_state()\n"); return bActionAllowed; } @@ -300,7 +290,7 @@ static void rtl8192_tx_timeout(struct net_device *dev) netdev_info(dev, "TXTIMEOUT"); } -void rtl8192_irq_enable(struct net_device *dev) +void rtl92e_irq_enable(struct net_device *dev) { struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); @@ -309,7 +299,7 @@ void rtl8192_irq_enable(struct net_device *dev) priv->ops->irq_enable(dev); } -void rtl8192_irq_disable(struct net_device *dev) +void rtl92e_irq_disable(struct net_device *dev) { struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); @@ -525,7 +515,7 @@ static int rtl8192_qos_association_resp(struct r8192_priv *priv, RT_TRACE(COMP_QOS, "%s: network->flags = %d,%d\n", __func__, network->flags, priv->rtllib->current_network.qos_data.active); if (set_qos_param == 1) { - dm_init_edca_turbo(priv->rtllib->dev); + rtl92e_dm_init_edca_turbo(priv->rtllib->dev); queue_work_rsl(priv->priv_wq, &priv->qos_activate); } return 0; @@ -575,7 +565,7 @@ static void rtl8192_stop_beacon(struct net_device *dev) { } -void rtl8192_config_rate(struct net_device *dev, u16 *rate_config) +void rtl92e_config_rate(struct net_device *dev, u16 *rate_config) { struct r8192_priv *priv = rtllib_priv(dev); struct rtllib_network *net; @@ -706,7 +696,7 @@ static u8 rtl8192_getSupportedWireleeMode(struct net_device *dev) return ret; } -void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode) +void rtl92e_set_wireless_mode(struct net_device *dev, u8 wireless_mode) { struct r8192_priv *priv = rtllib_priv(dev); u8 bSupportMode = rtl8192_getSupportedWireleeMode(dev); @@ -737,9 +727,6 @@ void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode) priv->rtllib->mode = wireless_mode; - ActUpdateChannelAccessSetting(dev, wireless_mode, - &priv->ChannelAccessSetting); - if ((wireless_mode == WIRELESS_MODE_N_24G) || (wireless_mode == WIRELESS_MODE_N_5G)) { priv->rtllib->pHTInfo->bEnableHT = 1; @@ -783,7 +770,7 @@ static int _rtl8192_sta_up(struct net_device *dev, bool is_silent_reset) priv->bfirst_init = false; if (priv->polling_timer_on == 0) - check_rfctrl_gpio_timer((unsigned long)dev); + rtl92e_check_rfctrl_gpio_timer((unsigned long)dev); if (priv->rtllib->state != RTLLIB_LINKED) rtllib_softmac_start_protocol(priv->rtllib, 0); @@ -811,7 +798,7 @@ static int rtl8192_sta_down(struct net_device *dev, bool shutdownrf) priv->rtllib->rtllib_ips_leave(dev); if (priv->rtllib->state == RTLLIB_LINKED) - LeisurePSLeave(dev); + rtl92e_leisure_ps_leave(dev); priv->bDriverIsGoingToUnload = true; priv->up = 0; @@ -824,9 +811,9 @@ static int rtl8192_sta_down(struct net_device *dev, bool shutdownrf) priv->rtllib->wpa_ie_len = 0; kfree(priv->rtllib->wpa_ie); priv->rtllib->wpa_ie = NULL; - CamResetAllEntry(dev); + rtl92e_cam_reset(dev); memset(priv->rtllib->swcamtable, 0, sizeof(struct sw_cam_table) * 32); - rtl8192_irq_disable(dev); + rtl92e_irq_disable(dev); del_timer_sync(&priv->watch_dog_timer); rtl8192_cancel_deferred_work(priv); @@ -869,38 +856,36 @@ static void rtl8192_init_priv_handler(struct net_device *dev) priv->rtllib->set_chan = rtl8192_set_chan; priv->rtllib->link_change = priv->ops->link_change; priv->rtllib->softmac_data_hard_start_xmit = rtl8192_hard_data_xmit; - priv->rtllib->data_hard_stop = rtl8192_data_hard_stop; - priv->rtllib->data_hard_resume = rtl8192_data_hard_resume; priv->rtllib->check_nic_enough_desc = rtl8192_check_nic_enough_desc; priv->rtllib->handle_assoc_response = rtl8192_handle_assoc_response; priv->rtllib->handle_beacon = rtl8192_handle_beacon; - priv->rtllib->SetWirelessMode = rtl8192_SetWirelessMode; - priv->rtllib->LeisurePSLeave = LeisurePSLeave; - priv->rtllib->SetBWModeHandler = rtl8192_SetBWMode; - priv->rf_set_chan = rtl8192_phy_SwChnl; + priv->rtllib->SetWirelessMode = rtl92e_set_wireless_mode; + priv->rtllib->LeisurePSLeave = rtl92e_leisure_ps_leave; + priv->rtllib->SetBWModeHandler = rtl92e_set_bw_mode; + priv->rf_set_chan = rtl92e_set_channel; - priv->rtllib->start_send_beacons = rtl8192e_start_beacon; + priv->rtllib->start_send_beacons = rtl92e_start_beacon; priv->rtllib->stop_send_beacons = rtl8192_stop_beacon; - priv->rtllib->sta_wake_up = rtl8192_hw_wakeup; - priv->rtllib->enter_sleep_state = rtl8192_hw_to_sleep; + priv->rtllib->sta_wake_up = rtl92e_hw_wakeup; + priv->rtllib->enter_sleep_state = rtl92e_enter_sleep; priv->rtllib->ps_is_queue_empty = rtl8192_is_tx_queue_empty; - priv->rtllib->GetNmodeSupportBySecCfg = rtl8192_GetNmodeSupportBySecCfg; + priv->rtllib->GetNmodeSupportBySecCfg = rtl92e_get_nmode_support_by_sec; priv->rtllib->GetHalfNmodeSupportByAPsHandler = - rtl8192_GetHalfNmodeSupportByAPs; + rtl92e_is_halfn_supported_by_ap; - priv->rtllib->SetHwRegHandler = rtl8192e_SetHwReg; - priv->rtllib->AllowAllDestAddrHandler = rtl8192_AllowAllDestAddr; + priv->rtllib->SetHwRegHandler = rtl92e_set_reg; + priv->rtllib->AllowAllDestAddrHandler = rtl92e_set_monitor_mode; priv->rtllib->SetFwCmdHandler = NULL; - priv->rtllib->InitialGainHandler = InitialGain819xPci; - priv->rtllib->rtllib_ips_leave_wq = rtllib_ips_leave_wq; - priv->rtllib->rtllib_ips_leave = rtllib_ips_leave; + priv->rtllib->InitialGainHandler = rtl92e_init_gain; + priv->rtllib->rtllib_ips_leave_wq = rtl92e_rtllib_ips_leave_wq; + priv->rtllib->rtllib_ips_leave = rtl92e_rtllib_ips_leave; priv->rtllib->LedControlHandler = NULL; priv->rtllib->UpdateBeaconInterruptHandler = NULL; - priv->rtllib->ScanOperationBackupHandler = PHY_ScanOperationBackup8192; + priv->rtllib->ScanOperationBackupHandler = rtl92e_scan_op_backup; } static void rtl8192_init_priv_constant(struct net_device *dev) @@ -1023,20 +1008,21 @@ static void rtl8192_init_priv_task(struct net_device *dev) priv->priv_wq = create_workqueue(DRV_NAME); INIT_WORK_RSL(&priv->reset_wq, (void *)rtl8192_restart, dev); - INIT_WORK_RSL(&priv->rtllib->ips_leave_wq, (void *)IPSLeave_wq, dev); + INIT_WORK_RSL(&priv->rtllib->ips_leave_wq, (void *)rtl92e_ips_leave_wq, + dev); INIT_DELAYED_WORK_RSL(&priv->watch_dog_wq, (void *)rtl819x_watchdog_wqcallback, dev); INIT_DELAYED_WORK_RSL(&priv->txpower_tracking_wq, - (void *)dm_txpower_trackingcallback, dev); + (void *)rtl92e_dm_txpower_tracking_wq, dev); INIT_DELAYED_WORK_RSL(&priv->rfpath_check_wq, - (void *)dm_rf_pathcheck_workitemcallback, dev); + (void *)rtl92e_dm_rf_pathcheck_wq, dev); INIT_DELAYED_WORK_RSL(&priv->update_beacon_wq, (void *)rtl8192_update_beacon, dev); INIT_WORK_RSL(&priv->qos_activate, (void *)rtl8192_qos_activate, dev); INIT_DELAYED_WORK_RSL(&priv->rtllib->hw_wakeup_wq, - (void *) rtl8192_hw_wakeup_wq, dev); + (void *) rtl92e_hw_wakeup_wq, dev); INIT_DELAYED_WORK_RSL(&priv->rtllib->hw_sleep_wq, - (void *) rtl8192_hw_sleep_wq, dev); + (void *) rtl92e_hw_sleep_wq, dev); tasklet_init(&priv->irq_rx_tasklet, (void(*)(unsigned long))rtl8192_irq_rx_tasklet, (unsigned long)priv); @@ -1092,17 +1078,17 @@ static short rtl8192_init(struct net_device *dev) priv->ops->init_adapter_variable(dev); rtl8192_get_channel_map(dev); - init_hal_dm(dev); + rtl92e_dm_init(dev); setup_timer(&priv->watch_dog_timer, watch_dog_timer_callback, (unsigned long) dev); setup_timer(&priv->gpio_polling_timer, - check_rfctrl_gpio_timer, + rtl92e_check_rfctrl_gpio_timer, (unsigned long)dev); - rtl8192_irq_disable(dev); + rtl92e_irq_disable(dev); if (request_irq(dev->irq, rtl8192_interrupt, IRQF_SHARED, dev->name, dev)) { netdev_err(dev, "Error allocating IRQ %d", dev->irq); @@ -1281,7 +1267,7 @@ RESET_START: down(&priv->wx_sem); if (priv->rtllib->state == RTLLIB_LINKED) - LeisurePSLeave(dev); + rtl92e_leisure_ps_leave(dev); if (priv->up) { netdev_info(dev, "%s():the driver is not up.\n", @@ -1301,10 +1287,10 @@ RESET_START: if (!netif_queue_stopped(dev)) netif_stop_queue(dev); - rtl8192_irq_disable(dev); + rtl92e_irq_disable(dev); del_timer_sync(&priv->watch_dog_timer); rtl8192_cancel_deferred_work(priv); - deinit_hal_dm(dev); + rtl92e_dm_deinit(dev); rtllib_stop_scan_syncro(ieee); if (ieee->state == RTLLIB_LINKED) { @@ -1321,7 +1307,7 @@ RESET_START: rtllib_softmac_stop_protocol(priv->rtllib, 0, true); } - dm_backup_dynamic_mechanism_state(dev); + rtl92e_dm_backup_state(dev); up(&priv->wx_sem); RT_TRACE(COMP_RESET, @@ -1350,7 +1336,7 @@ RESET_START: priv->RFChangeInProgress = false; spin_unlock_irqrestore(&priv->rf_ps_lock, flag); - EnableHWSecurityConfig8192(dev); + rtl92e_enable_hw_security_config(dev); if (ieee->state == RTLLIB_LINKED && ieee->iw_mode == IW_MODE_INFRA) { @@ -1369,15 +1355,13 @@ RESET_START: rtllib_start_send_beacons(ieee); - if (ieee->data_hard_resume) - ieee->data_hard_resume(ieee->dev); netif_carrier_on(ieee->dev); } else if (ieee->iw_mode == IW_MODE_MESH) { rtl819x_silentreset_mesh_bk(dev, IsPortal); } - CamRestoreAllEntry(dev); - dm_restore_dynamic_mechanism_state(dev); + rtl92e_cam_restore(dev); + rtl92e_dm_restore_state(dev); END: priv->ResetProgress = RESET_TYPE_NORESET; priv->reset_count++; @@ -1385,7 +1369,7 @@ END: priv->bForcedSilentReset = false; priv->bResetInProgress = false; - write_nic_byte(dev, UFWP, 1); + rtl92e_writeb(dev, UFWP, 1); RT_TRACE(COMP_RESET, "Reset finished!! ====>[%d]\n", priv->reset_count); } @@ -1438,7 +1422,7 @@ static void rtl819x_watchdog_wqcallback(void *data) priv->rtllib->CntAfterLink = 0; } - hal_dm_watchdog(dev); + rtl92e_dm_watchdog(dev); if (rtllib_act_scanning(priv->rtllib, false) == false) { if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->state == @@ -1449,8 +1433,8 @@ static void rtl819x_watchdog_wqcallback(void *data) IPS_CALLBACK_NONE) && (!ieee->bNetPromiscuousMode)) { RT_TRACE(COMP_PS, - "====================>haha: IPSEnter()\n"); - IPSEnter(dev); + "====================>haha: rtl92e_ips_enter()\n"); + rtl92e_ips_enter(dev); } } } @@ -1481,13 +1465,13 @@ static void rtl819x_watchdog_wqcallback(void *data) bEnterPS = false; if (bEnterPS) - LeisurePSEnter(dev); + rtl92e_leisure_ps_enter(dev); else - LeisurePSLeave(dev); + rtl92e_leisure_ps_leave(dev); } else { RT_TRACE(COMP_LPS, "====>no link LPS leave\n"); - LeisurePSLeave(dev); + rtl92e_leisure_ps_leave(dev); } ieee->LinkDetectInfo.NumRxOkInPeriod = 0; @@ -1578,14 +1562,14 @@ static void watch_dog_timer_callback(unsigned long data) /**************************************************************************** ---------------------------- NIC TX/RX STUFF--------------------------- *****************************************************************************/ -void rtl8192_rx_enable(struct net_device *dev) +void rtl92e_rx_enable(struct net_device *dev) { struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); priv->ops->rx_enable(dev); } -void rtl8192_tx_enable(struct net_device *dev) +void rtl92e_tx_enable(struct net_device *dev) { struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); @@ -1643,14 +1627,6 @@ static void rtl8192_free_tx_ring(struct net_device *dev, unsigned int prio) ring->desc = NULL; } -static void rtl8192_data_hard_stop(struct net_device *dev) -{ -} - -static void rtl8192_data_hard_resume(struct net_device *dev) -{ -} - static void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int rate) { @@ -1837,7 +1813,7 @@ static short rtl8192_tx(struct net_device *dev, struct sk_buff *skb) spin_unlock_irqrestore(&priv->irq_th_lock, flags); dev->trans_start = jiffies; - write_nic_word(dev, TPPoll, 0x01 << tcb_desc->queue_index); + rtl92e_writew(dev, TPPoll, 0x01 << tcb_desc->queue_index); return 0; } @@ -1943,7 +1919,7 @@ err_free_rings: return 1; } -void rtl8192_pci_resetdescring(struct net_device *dev) +void rtl92e_reset_desc_ring(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); int i, rx_queue_idx; @@ -1983,8 +1959,8 @@ void rtl8192_pci_resetdescring(struct net_device *dev) spin_unlock_irqrestore(&priv->irq_th_lock, flags); } -void rtl819x_UpdateRxPktTimeStamp(struct net_device *dev, - struct rtllib_rx_stats *stats) +void rtl92e_update_rx_pkt_timestamp(struct net_device *dev, + struct rtllib_rx_stats *stats) { struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); @@ -1994,7 +1970,7 @@ void rtl819x_UpdateRxPktTimeStamp(struct net_device *dev, priv->LastRxDescTSF = stats->mac_time; } -long rtl819x_translate_todbm(struct r8192_priv *priv, u8 signal_strength_index) +long rtl92e_translate_to_dbm(struct r8192_priv *priv, u8 signal_strength_index) { long signal_power; @@ -2005,11 +1981,8 @@ long rtl819x_translate_todbm(struct r8192_priv *priv, u8 signal_strength_index) } -void -rtl819x_update_rxsignalstatistics8190pci( - struct r8192_priv *priv, - struct rtllib_rx_stats *pprevious_stats - ) +void rtl92e_update_rx_statistics(struct r8192_priv *priv, + struct rtllib_rx_stats *pprevious_stats) { int weighting = 0; @@ -2028,7 +2001,7 @@ rtl819x_update_rxsignalstatistics8190pci( weighting) / 6; } -u8 rtl819x_query_rxpwrpercentage(char antpower) +u8 rtl92e_rx_db_to_percent(char antpower) { if ((antpower <= -100) || (antpower >= 20)) return 0; @@ -2039,10 +2012,7 @@ u8 rtl819x_query_rxpwrpercentage(char antpower) } /* QueryRxPwrPercentage */ -u8 -rtl819x_evm_dbtopercentage( - char value - ) +u8 rtl92e_evm_db_to_percent(char value) { char ret_val; @@ -2059,11 +2029,8 @@ rtl819x_evm_dbtopercentage( return ret_val; } -void -rtl8192_record_rxdesc_forlateruse( - struct rtllib_rx_stats *psrc_stats, - struct rtllib_rx_stats *ptarget_stats -) +void rtl92e_copy_mpdu_stats(struct rtllib_rx_stats *psrc_stats, + struct rtllib_rx_stats *ptarget_stats) { ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU; ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU; @@ -2203,8 +2170,8 @@ static void rtl8192_irq_rx_tasklet(struct r8192_priv *priv) { rtl8192_rx_normal(priv->rtllib->dev); - write_nic_dword(priv->rtllib->dev, INTA_MASK, - read_nic_dword(priv->rtllib->dev, INTA_MASK) | IMR_RDU); + rtl92e_writel(priv->rtllib->dev, INTA_MASK, + rtl92e_readl(priv->rtllib->dev, INTA_MASK) | IMR_RDU); } /**************************************************************************** @@ -2276,14 +2243,14 @@ static int rtl8192_down(struct net_device *dev, bool shutdownrf) return 0; } -void rtl8192_commit(struct net_device *dev) +void rtl92e_commit(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); if (priv->up == 0) return; rtllib_softmac_stop_protocol(priv->rtllib, 0, true); - rtl8192_irq_disable(dev); + rtl92e_irq_disable(dev); priv->ops->stop_adapter(dev, true); _rtl8192_up(dev, false); } @@ -2296,7 +2263,7 @@ static void rtl8192_restart(void *data) down(&priv->wx_sem); - rtl8192_commit(dev); + rtl92e_commit(dev); up(&priv->wx_sem); } @@ -2375,30 +2342,34 @@ static int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) if (is_zero_ether_addr(ieee->ap_mac_addr)) ieee->iw_mode = IW_MODE_ADHOC; memcpy((u8 *)key, ipw->u.crypt.key, 16); - EnableHWSecurityConfig8192(dev); - set_swcam(dev, 4, ipw->u.crypt.idx, - ieee->pairwise_key_type, - (u8 *)ieee->ap_mac_addr, - 0, key, 0); - setKey(dev, 4, ipw->u.crypt.idx, - ieee->pairwise_key_type, - (u8 *)ieee->ap_mac_addr, 0, key); - if (ieee->iw_mode == IW_MODE_ADHOC) { - set_swcam(dev, ipw->u.crypt.idx, - ipw->u.crypt.idx, - ieee->pairwise_key_type, - (u8 *)ieee->ap_mac_addr, - 0, key, 0); - setKey(dev, ipw->u.crypt.idx, - ipw->u.crypt.idx, + rtl92e_enable_hw_security_config(dev); + rtl92e_set_swcam(dev, 4, + ipw->u.crypt.idx, + ieee->pairwise_key_type, + (u8 *)ieee->ap_mac_addr, + 0, key, 0); + rtl92e_set_key(dev, 4, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8 *)ieee->ap_mac_addr, 0, key); + if (ieee->iw_mode == IW_MODE_ADHOC) { + rtl92e_set_swcam(dev, + ipw->u.crypt.idx, + ipw->u.crypt.idx, + ieee->pairwise_key_type, + (u8 *)ieee->ap_mac_addr, + 0, key, 0); + rtl92e_set_key(dev, + ipw->u.crypt.idx, + ipw->u.crypt.idx, + ieee->pairwise_key_type, + (u8 *)ieee->ap_mac_addr, + 0, key); } } if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport) { - write_nic_byte(dev, 0x173, 1); + rtl92e_writeb(dev, 0x173, 1); } } else { @@ -2418,14 +2389,15 @@ static int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ieee->group_key_type = KEY_TYPE_NA; if (ieee->group_key_type) { - set_swcam(dev, ipw->u.crypt.idx, - ipw->u.crypt.idx, - ieee->group_key_type, - broadcast_addr, 0, key, 0); - setKey(dev, ipw->u.crypt.idx, - ipw->u.crypt.idx, - ieee->group_key_type, - broadcast_addr, 0, key); + rtl92e_set_swcam(dev, ipw->u.crypt.idx, + ipw->u.crypt.idx, + ieee->group_key_type, + broadcast_addr, 0, key, + 0); + rtl92e_set_key(dev, ipw->u.crypt.idx, + ipw->u.crypt.idx, + ieee->group_key_type, + broadcast_addr, 0, key); } } } @@ -2530,8 +2502,8 @@ static irqreturn_t rtl8192_interrupt(int irq, void *netdev) if (inta & IMR_RDU) { RT_TRACE(COMP_INTR, "rx descriptor unavailable!\n"); priv->stats.rxrdu++; - write_nic_dword(dev, INTA_MASK, - read_nic_dword(dev, INTA_MASK) & ~IMR_RDU); + rtl92e_writel(dev, INTA_MASK, + rtl92e_readl(dev, INTA_MASK) & ~IMR_RDU); tasklet_schedule(&priv->irq_rx_tasklet); } @@ -2670,12 +2642,12 @@ static int rtl8192_pci_probe(struct pci_dev *pdev, pci_read_config_byte(pdev, 0x08, &revision_id); /* If the revisionid is 0x10, the device uses rtl8192se. */ if (pdev->device == 0x8192 && revision_id == 0x10) - goto err_rel_mem; + goto err_unmap; priv->ops = ops; - if (rtl8192_pci_findadapter(pdev, dev) == false) - goto err_rel_mem; + if (rtl92e_check_adapter(pdev, dev) == false) + goto err_unmap; dev->irq = pdev->irq; priv->irq = 0; @@ -2708,7 +2680,7 @@ static int rtl8192_pci_probe(struct pci_dev *pdev, RT_TRACE(COMP_INIT, "dev name: %s\n", dev->name); if (priv->polling_timer_on == 0) - check_rfctrl_gpio_timer((unsigned long)dev); + rtl92e_check_rfctrl_gpio_timer((unsigned long)dev); RT_TRACE(COMP_INIT, "Driver probe completed\n"); return 0; @@ -2716,6 +2688,8 @@ static int rtl8192_pci_probe(struct pci_dev *pdev, err_free_irq: free_irq(dev->irq, dev); priv->irq = 0; +err_unmap: + iounmap((void __iomem *)ioaddr); err_rel_mem: release_mem_region(pmem_start, pmem_len); err_rel_rtllib: @@ -2740,7 +2714,7 @@ static void rtl8192_pci_disconnect(struct pci_dev *pdev) cancel_delayed_work(&priv->gpio_change_rf_wq); priv->polling_timer_on = 0; rtl8192_down(dev, true); - deinit_hal_dm(dev); + rtl92e_dm_deinit(dev); if (priv->pFirmware) { vfree(priv->pFirmware); priv->pFirmware = NULL; @@ -2770,7 +2744,7 @@ static void rtl8192_pci_disconnect(struct pci_dev *pdev) RT_TRACE(COMP_DOWN, "wlan driver removed\n"); } -bool NicIFEnableNIC(struct net_device *dev) +bool rtl92e_enable_nic(struct net_device *dev) { bool init_status = true; struct r8192_priv *priv = rtllib_priv(dev); @@ -2795,12 +2769,12 @@ bool NicIFEnableNIC(struct net_device *dev) RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC); priv->bfirst_init = false; - rtl8192_irq_enable(dev); + rtl92e_irq_enable(dev); priv->bdisable_nic = false; RT_TRACE(COMP_PS, "<===========%s()\n", __func__); return init_status; } -bool NicIFDisableNIC(struct net_device *dev) +bool rtl92e_disable_nic(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); u8 tmp_state = 0; @@ -2811,7 +2785,7 @@ bool NicIFDisableNIC(struct net_device *dev) rtllib_softmac_stop_protocol(priv->rtllib, 0, false); priv->rtllib->state = tmp_state; rtl8192_cancel_deferred_work(priv); - rtl8192_irq_disable(dev); + rtl92e_irq_disable(dev); priv->ops->stop_adapter(dev, false); RT_TRACE(COMP_PS, "<=========%s()\n", __func__); @@ -2838,7 +2812,7 @@ static void __exit rtl8192_pci_module_exit(void) RT_TRACE(COMP_DOWN, "Exiting"); } -void check_rfctrl_gpio_timer(unsigned long data) +void rtl92e_check_rfctrl_gpio_timer(unsigned long data) { struct r8192_priv *priv = rtllib_priv((struct net_device *)data); diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h index 26e54e41ced6..cd948bb13840 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h @@ -578,51 +578,44 @@ struct r8192_priv { extern const struct ethtool_ops rtl819x_ethtool_ops; -u8 read_nic_byte(struct net_device *dev, int x); -u32 read_nic_dword(struct net_device *dev, int x); -u16 read_nic_word(struct net_device *dev, int x); -void write_nic_byte(struct net_device *dev, int x, u8 y); -void write_nic_word(struct net_device *dev, int x, u16 y); -void write_nic_dword(struct net_device *dev, int x, u32 y); +u8 rtl92e_readb(struct net_device *dev, int x); +u32 rtl92e_readl(struct net_device *dev, int x); +u16 rtl92e_readw(struct net_device *dev, int x); +void rtl92e_writeb(struct net_device *dev, int x, u8 y); +void rtl92e_writew(struct net_device *dev, int x, u16 y); +void rtl92e_writel(struct net_device *dev, int x, u32 y); void force_pci_posting(struct net_device *dev); -void rtl8192_rx_enable(struct net_device *); -void rtl8192_tx_enable(struct net_device *); +void rtl92e_rx_enable(struct net_device *); +void rtl92e_tx_enable(struct net_device *); -void rtl8192_hw_sleep_wq(void *data); -void rtl8192_commit(struct net_device *dev); +void rtl92e_hw_sleep_wq(void *data); +void rtl92e_commit(struct net_device *dev); -void check_rfctrl_gpio_timer(unsigned long data); +void rtl92e_check_rfctrl_gpio_timer(unsigned long data); -void rtl8192_hw_wakeup_wq(void *data); +void rtl92e_hw_wakeup_wq(void *data); -void rtl8192_irq_disable(struct net_device *dev); +void rtl92e_reset_desc_ring(struct net_device *dev); +void rtl92e_set_wireless_mode(struct net_device *dev, u8 wireless_mode); +void rtl92e_irq_enable(struct net_device *dev); +void rtl92e_config_rate(struct net_device *dev, u16 *rate_config); +void rtl92e_irq_disable(struct net_device *dev); -void rtl8192_pci_resetdescring(struct net_device *dev); -void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode); -void rtl8192_irq_enable(struct net_device *dev); -void rtl8192_config_rate(struct net_device *dev, u16 *rate_config); -void rtl8192_irq_disable(struct net_device *dev); +void rtl92e_update_rx_pkt_timestamp(struct net_device *dev, + struct rtllib_rx_stats *stats); +long rtl92e_translate_to_dbm(struct r8192_priv *priv, u8 signal_strength_index); +void rtl92e_update_rx_statistics(struct r8192_priv *priv, + struct rtllib_rx_stats *pprevious_stats); +u8 rtl92e_evm_db_to_percent(char value); +u8 rtl92e_rx_db_to_percent(char antpower); +void rtl92e_copy_mpdu_stats(struct rtllib_rx_stats *psrc_stats, + struct rtllib_rx_stats *ptarget_stats); +bool rtl92e_enable_nic(struct net_device *dev); +bool rtl92e_disable_nic(struct net_device *dev); -void rtl819x_UpdateRxPktTimeStamp(struct net_device *dev, - struct rtllib_rx_stats *stats); -long rtl819x_translate_todbm(struct r8192_priv *priv, u8 signal_strength_index); -void rtl819x_update_rxsignalstatistics8190pci(struct r8192_priv *priv, - struct rtllib_rx_stats *pprevious_stats); -u8 rtl819x_evm_dbtopercentage(char value); -u8 rtl819x_query_rxpwrpercentage(char antpower); -void rtl8192_record_rxdesc_forlateruse(struct rtllib_rx_stats *psrc_stats, - struct rtllib_rx_stats *ptarget_stats); -bool NicIFEnableNIC(struct net_device *dev); -bool NicIFDisableNIC(struct net_device *dev); - -bool MgntActSet_RF_State(struct net_device *dev, +bool rtl92e_set_rf_state(struct net_device *dev, enum rt_rf_power_state StateToSet, - RT_RF_CHANGE_SOURCE ChangeSource, - bool ProtectOrNot); -void ActUpdateChannelAccessSetting(struct net_device *dev, - enum wireless_mode WirelessMode, - struct channel_access_setting *ChnlAccessSetting); - + RT_RF_CHANGE_SOURCE ChangeSource); #endif diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c index c2367128c594..1a0c690bfa07 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c @@ -224,7 +224,7 @@ static void dm_send_rssi_tofw(struct net_device *dev); static void dm_ctstoself(struct net_device *dev); /*---------------------------Define function prototype------------------------*/ -void init_hal_dm(struct net_device *dev) +void rtl92e_dm_init(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); @@ -234,10 +234,10 @@ void init_hal_dm(struct net_device *dev) dm_init_dynamic_txpower(dev); - init_rate_adaptive(dev); + rtl92e_init_adaptive_rate(dev); dm_dig_init(dev); - dm_init_edca_turbo(dev); + rtl92e_dm_init_edca_turbo(dev); dm_init_bandwidth_autoswitch(dev); dm_init_fsync(dev); dm_init_rxpath_selection(dev); @@ -249,14 +249,14 @@ void init_hal_dm(struct net_device *dev) (void *)dm_CheckRfCtrlGPIO, dev); } -void deinit_hal_dm(struct net_device *dev) +void rtl92e_dm_deinit(struct net_device *dev) { dm_deInit_fsync(dev); } -void hal_dm_watchdog(struct net_device *dev) +void rtl92e_dm_watchdog(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); @@ -307,7 +307,7 @@ static void dm_check_ac_dc_power(struct net_device *dev) }; -void init_rate_adaptive(struct net_device *dev) +void rtl92e_init_adaptive_rate(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); @@ -444,7 +444,7 @@ static void dm_check_rate_adaptive(struct net_device *dev) if (priv->rtllib->GetHalfNmodeSupportByAPsHandler(dev)) targetRATR &= 0xf00fffff; - currentRATR = read_nic_dword(dev, RATR0); + currentRATR = rtl92e_readl(dev, RATR0); if (targetRATR != currentRATR) { u32 ratr_value; @@ -454,8 +454,8 @@ static void dm_check_rate_adaptive(struct net_device *dev) currentRATR, targetRATR); if (priv->rf_type == RF_1T2R) ratr_value &= ~(RATE_ALL_OFDM_2SS); - write_nic_dword(dev, RATR0, ratr_value); - write_nic_byte(dev, UFWP, 1); + rtl92e_writel(dev, RATR0, ratr_value); + rtl92e_writeb(dev, UFWP, 1); pra->last_ratr = targetRATR; } @@ -561,40 +561,40 @@ static void dm_tx_update_tssi_weak_signal(struct net_device *dev, u8 RF_Type) p->rfa_txpowertrackingindex--; if (p->rfa_txpowertrackingindex_real > 4) { p->rfa_txpowertrackingindex_real--; - rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, - bMaskDWord, - dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]); + rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance, + bMaskDWord, + dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]); } p->rfc_txpowertrackingindex--; if (p->rfc_txpowertrackingindex_real > 4) { p->rfc_txpowertrackingindex_real--; - rtl8192_setBBreg(dev, - rOFDM0_XCTxIQImbalance, - bMaskDWord, - dm_tx_bb_gain[p->rfc_txpowertrackingindex_real]); + rtl92e_set_bb_reg(dev, + rOFDM0_XCTxIQImbalance, + bMaskDWord, + dm_tx_bb_gain[p->rfc_txpowertrackingindex_real]); } } else { - rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, - bMaskDWord, - dm_tx_bb_gain[4]); - rtl8192_setBBreg(dev, - rOFDM0_XCTxIQImbalance, - bMaskDWord, dm_tx_bb_gain[4]); + rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance, + bMaskDWord, + dm_tx_bb_gain[4]); + rtl92e_set_bb_reg(dev, + rOFDM0_XCTxIQImbalance, + bMaskDWord, dm_tx_bb_gain[4]); } } else { if (p->rfa_txpowertrackingindex > 0) { p->rfa_txpowertrackingindex--; if (p->rfa_txpowertrackingindex_real > 4) { p->rfa_txpowertrackingindex_real--; - rtl8192_setBBreg(dev, - rOFDM0_XATxIQImbalance, - bMaskDWord, - dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]); + rtl92e_set_bb_reg(dev, + rOFDM0_XATxIQImbalance, + bMaskDWord, + dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]); } } else { - rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, - bMaskDWord, dm_tx_bb_gain[4]); + rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance, + bMaskDWord, dm_tx_bb_gain[4]); } } } @@ -608,36 +608,33 @@ static void dm_tx_update_tssi_strong_signal(struct net_device *dev, u8 RF_Type) (p->rfc_txpowertrackingindex < TxBBGainTableLength - 1)) { p->rfa_txpowertrackingindex++; p->rfa_txpowertrackingindex_real++; - rtl8192_setBBreg(dev, - rOFDM0_XATxIQImbalance, - bMaskDWord, - dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]); + rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance, + bMaskDWord, + dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]); p->rfc_txpowertrackingindex++; p->rfc_txpowertrackingindex_real++; - rtl8192_setBBreg(dev, - rOFDM0_XCTxIQImbalance, - bMaskDWord, - dm_tx_bb_gain[p->rfc_txpowertrackingindex_real]); + rtl92e_set_bb_reg(dev, rOFDM0_XCTxIQImbalance, + bMaskDWord, + dm_tx_bb_gain[p->rfc_txpowertrackingindex_real]); } else { - rtl8192_setBBreg(dev, - rOFDM0_XATxIQImbalance, - bMaskDWord, - dm_tx_bb_gain[TxBBGainTableLength - 1]); - rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, - bMaskDWord, - dm_tx_bb_gain[TxBBGainTableLength - 1]); + rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance, + bMaskDWord, + dm_tx_bb_gain[TxBBGainTableLength - 1]); + rtl92e_set_bb_reg(dev, rOFDM0_XCTxIQImbalance, + bMaskDWord, + dm_tx_bb_gain[TxBBGainTableLength - 1]); } } else { if (p->rfa_txpowertrackingindex < (TxBBGainTableLength - 1)) { p->rfa_txpowertrackingindex++; p->rfa_txpowertrackingindex_real++; - rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, - bMaskDWord, - dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]); + rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance, + bMaskDWord, + dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]); } else { - rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, - bMaskDWord, - dm_tx_bb_gain[TxBBGainTableLength - 1]); + rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance, + bMaskDWord, + dm_tx_bb_gain[TxBBGainTableLength - 1]); } } } @@ -656,8 +653,8 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) u32 delta = 0; RT_TRACE(COMP_POWER_TRACKING, "%s()\n", __func__); - write_nic_byte(dev, Pw_Track_Flag, 0); - write_nic_byte(dev, FW_Busy_Flag, 0); + rtl92e_writeb(dev, Pw_Track_Flag, 0); + rtl92e_writeb(dev, FW_Busy_Flag, 0); priv->rtllib->bdynamic_txpower_enable = false; bHighpowerstate = priv->bDynamicTxHighPower; @@ -674,12 +671,11 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) tx_cmd.Op = TXCMD_SET_TX_PWR_TRACKING; tx_cmd.Length = 4; tx_cmd.Value = Value; - cmpk_message_handle_tx(dev, (u8 *)&tx_cmd, - DESC_PACKET_TYPE_INIT, - sizeof(struct dcmd_txcmd)); + rtl92e_send_cmd_pkt(dev, (u8 *)&tx_cmd, DESC_PACKET_TYPE_INIT, + sizeof(struct dcmd_txcmd)); mdelay(1); for (i = 0; i <= 30; i++) { - Pwr_Flag = read_nic_byte(dev, Pw_Track_Flag); + Pwr_Flag = rtl92e_readb(dev, Pw_Track_Flag); if (Pwr_Flag == 0) { mdelay(1); @@ -687,35 +683,35 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) if (priv->bResetInProgress) { RT_TRACE(COMP_POWER_TRACKING, "we are in silent reset progress, so return\n"); - write_nic_byte(dev, Pw_Track_Flag, 0); - write_nic_byte(dev, FW_Busy_Flag, 0); + rtl92e_writeb(dev, Pw_Track_Flag, 0); + rtl92e_writeb(dev, FW_Busy_Flag, 0); return; } if (priv->rtllib->eRFPowerState != eRfOn) { RT_TRACE(COMP_POWER_TRACKING, "we are in power save, so return\n"); - write_nic_byte(dev, Pw_Track_Flag, 0); - write_nic_byte(dev, FW_Busy_Flag, 0); + rtl92e_writeb(dev, Pw_Track_Flag, 0); + rtl92e_writeb(dev, FW_Busy_Flag, 0); return; } continue; } - Avg_TSSI_Meas = read_nic_word(dev, Tssi_Mea_Value); + Avg_TSSI_Meas = rtl92e_readw(dev, Tssi_Mea_Value); if (Avg_TSSI_Meas == 0) { - write_nic_byte(dev, Pw_Track_Flag, 0); - write_nic_byte(dev, FW_Busy_Flag, 0); + rtl92e_writeb(dev, Pw_Track_Flag, 0); + rtl92e_writeb(dev, FW_Busy_Flag, 0); return; } for (k = 0; k < 5; k++) { if (k != 4) - tmp_report[k] = read_nic_byte(dev, + tmp_report[k] = rtl92e_readb(dev, Tssi_Report_Value1+k); else - tmp_report[k] = read_nic_byte(dev, + tmp_report[k] = rtl92e_readb(dev, Tssi_Report_Value2); RT_TRACE(COMP_POWER_TRACKING, @@ -729,7 +725,7 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) } if (viviflag) { - write_nic_byte(dev, Pw_Track_Flag, 0); + rtl92e_writeb(dev, Pw_Track_Flag, 0); viviflag = false; RT_TRACE(COMP_POWER_TRACKING, "we filted this data\n"); @@ -756,8 +752,8 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) if (delta <= E_FOR_TX_POWER_TRACK) { priv->rtllib->bdynamic_txpower_enable = true; - write_nic_byte(dev, Pw_Track_Flag, 0); - write_nic_byte(dev, FW_Busy_Flag, 0); + rtl92e_writeb(dev, Pw_Track_Flag, 0); + rtl92e_writeb(dev, FW_Busy_Flag, 0); RT_TRACE(COMP_POWER_TRACKING, "tx power track is done\n"); RT_TRACE(COMP_POWER_TRACKING, @@ -806,12 +802,12 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) if (priv->rtllib->current_network.channel == 14 && !priv->bcck_in_ch14) { priv->bcck_in_ch14 = true; - dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); } else if (priv->rtllib->current_network.channel != 14 && priv->bcck_in_ch14) { priv->bcck_in_ch14 = false; - dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); } else - dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); } RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", @@ -829,23 +825,23 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) if (priv->CCKPresentAttentuation_difference <= -12 || priv->CCKPresentAttentuation_difference >= 24) { priv->rtllib->bdynamic_txpower_enable = true; - write_nic_byte(dev, Pw_Track_Flag, 0); - write_nic_byte(dev, FW_Busy_Flag, 0); + rtl92e_writeb(dev, Pw_Track_Flag, 0); + rtl92e_writeb(dev, FW_Busy_Flag, 0); RT_TRACE(COMP_POWER_TRACKING, "tx power track--->limited\n"); return; } - write_nic_byte(dev, Pw_Track_Flag, 0); + rtl92e_writeb(dev, Pw_Track_Flag, 0); Avg_TSSI_Meas_from_driver = 0; for (k = 0; k < 5; k++) tmp_report[k] = 0; break; } - write_nic_byte(dev, FW_Busy_Flag, 0); + rtl92e_writeb(dev, FW_Busy_Flag, 0); } priv->rtllib->bdynamic_txpower_enable = true; - write_nic_byte(dev, Pw_Track_Flag, 0); + rtl92e_writeb(dev, Pw_Track_Flag, 0); } static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev) @@ -857,8 +853,8 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev) int i = 0, CCKSwingNeedUpdate = 0; if (!priv->btxpower_trackingInit) { - tmpRegA = rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, - bMaskDWord); + tmpRegA = rtl92e_get_bb_reg(dev, rOFDM0_XATxIQImbalance, + bMaskDWord); for (i = 0; i < OFDM_Table_Length; i++) { if (tmpRegA == OFDMSwingTable[i]) { priv->OFDM_index[0] = (u8)i; @@ -869,7 +865,7 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev) } } - TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2); + TempCCk = rtl92e_get_bb_reg(dev, rCCK0_TxFilter1, bMaskByte2); for (i = 0; i < CCK_Table_length; i++) { if (TempCCk == (u32)CCKSwingTable_Ch1_Ch13[i][0]) { priv->CCK_index = (u8) i; @@ -884,7 +880,7 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev) return; } - tmpRegA = rtl8192_phy_QueryRFReg(dev, RF90_PATH_A, 0x12, 0x078); + tmpRegA = rtl92e_get_rf_reg(dev, RF90_PATH_A, 0x12, 0x078); RT_TRACE(COMP_POWER_TRACKING, "Readback ThermalMeterA = %d\n", tmpRegA); if (tmpRegA < 3 || tmpRegA > 13) return; @@ -939,11 +935,11 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev) } if (CCKSwingNeedUpdate) - dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); if (priv->OFDM_index[0] != tmpOFDMindex) { priv->OFDM_index[0] = tmpOFDMindex; - rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, - OFDMSwingTable[priv->OFDM_index[0]]); + rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, + OFDMSwingTable[priv->OFDM_index[0]]); RT_TRACE(COMP_POWER_TRACKING, "Update OFDMSwing[%d] = 0x%x\n", priv->OFDM_index[0], OFDMSwingTable[priv->OFDM_index[0]]); @@ -951,7 +947,7 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev) priv->txpower_count = 0; } -void dm_txpower_trackingcallback(void *data) +void rtl92e_dm_txpower_tracking_wq(void *data) { struct r8192_priv *priv = container_of_dwork_rsl(data, struct r8192_priv, txpower_tracking_wq); @@ -989,7 +985,7 @@ static void dm_InitializeTXPowerTracking_ThermalMeter(struct net_device *dev) priv->btxpower_tracking); } -void dm_initialize_txpower_tracking(struct net_device *dev) +void rtl92e_dm_init_txpower_tracking(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); @@ -1005,7 +1001,7 @@ static void dm_CheckTXPowerTracking_TSSI(struct net_device *dev) static u32 tx_power_track_counter; RT_TRACE(COMP_POWER_TRACKING, "%s()\n", __func__); - if (read_nic_byte(dev, 0x11e) == 1) + if (rtl92e_readb(dev, 0x11e) == 1) return; if (!priv->btxpower_tracking) return; @@ -1039,10 +1035,10 @@ static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev) if (!TM_Trigger) { { - rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d); - rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f); - rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d); - rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f); + rtl92e_set_rf_reg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d); + rtl92e_set_rf_reg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f); + rtl92e_set_rf_reg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d); + rtl92e_set_rf_reg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f); } TM_Trigger = 1; return; @@ -1074,30 +1070,30 @@ static void dm_CCKTxPowerAdjust_TSSI(struct net_device *dev, bool bInCH14) TempVal = (u32)(dm_cck_tx_bb_gain[attenuation][0] + (dm_cck_tx_bb_gain[attenuation][1] << 8)); - rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); + rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); TempVal = (u32)((dm_cck_tx_bb_gain[attenuation][2]) + (dm_cck_tx_bb_gain[attenuation][3] << 8) + (dm_cck_tx_bb_gain[attenuation][4] << 16)+ (dm_cck_tx_bb_gain[attenuation][5] << 24)); - rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); + rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); TempVal = (u32)(dm_cck_tx_bb_gain[attenuation][6] + (dm_cck_tx_bb_gain[attenuation][7] << 8)); - rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); + rtl92e_set_bb_reg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); } else { TempVal = (u32)((dm_cck_tx_bb_gain_ch14[attenuation][0]) + (dm_cck_tx_bb_gain_ch14[attenuation][1] << 8)); - rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); + rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); TempVal = (u32)((dm_cck_tx_bb_gain_ch14[attenuation][2]) + (dm_cck_tx_bb_gain_ch14[attenuation][3] << 8) + (dm_cck_tx_bb_gain_ch14[attenuation][4] << 16)+ (dm_cck_tx_bb_gain_ch14[attenuation][5] << 24)); - rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); + rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); TempVal = (u32)((dm_cck_tx_bb_gain_ch14[attenuation][6]) + (dm_cck_tx_bb_gain_ch14[attenuation][7] << 8)); - rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); + rtl92e_set_bb_reg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); } } @@ -1111,7 +1107,7 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, if (!bInCH14) { TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][0] + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][1] << 8); - rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); + rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n", rCCK0_TxFilter1, TempVal); @@ -1119,14 +1115,14 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, (CCKSwingTable_Ch1_Ch13[priv->CCK_index][3] << 8) + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][4] << 16)+ (CCKSwingTable_Ch1_Ch13[priv->CCK_index][5] << 24); - rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); + rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n", rCCK0_TxFilter2, TempVal); TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][6] + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][7] << 8); - rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); + rtl92e_set_bb_reg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n", rCCK0_DebugPort, TempVal); @@ -1134,26 +1130,26 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, TempVal = CCKSwingTable_Ch14[priv->CCK_index][0] + (CCKSwingTable_Ch14[priv->CCK_index][1] << 8); - rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); + rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n", rCCK0_TxFilter1, TempVal); TempVal = CCKSwingTable_Ch14[priv->CCK_index][2] + (CCKSwingTable_Ch14[priv->CCK_index][3] << 8) + (CCKSwingTable_Ch14[priv->CCK_index][4] << 16)+ (CCKSwingTable_Ch14[priv->CCK_index][5] << 24); - rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); + rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n", rCCK0_TxFilter2, TempVal); TempVal = CCKSwingTable_Ch14[priv->CCK_index][6] + (CCKSwingTable_Ch14[priv->CCK_index][7]<<8); - rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); + rtl92e_set_bb_reg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n", rCCK0_DebugPort, TempVal); } } -void dm_cck_txpower_adjust(struct net_device *dev, bool binch14) +void rtl92e_dm_cck_txpower_adjust(struct net_device *dev, bool binch14) { struct r8192_priv *priv = rtllib_priv(dev); @@ -1168,8 +1164,8 @@ static void dm_txpower_reset_recovery(struct net_device *dev) struct r8192_priv *priv = rtllib_priv(dev); RT_TRACE(COMP_POWER_TRACKING, "Start Reset Recovery ==>\n"); - rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, - dm_tx_bb_gain[priv->rfa_txpowertrackingindex]); + rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, + dm_tx_bb_gain[priv->rfa_txpowertrackingindex]); RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc80 is %08x\n", dm_tx_bb_gain[priv->rfa_txpowertrackingindex]); RT_TRACE(COMP_POWER_TRACKING, @@ -1181,10 +1177,10 @@ static void dm_txpower_reset_recovery(struct net_device *dev) RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: CCK Attenuation is %d dB\n", priv->CCKPresentAttentuation); - dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); - rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, - dm_tx_bb_gain[priv->rfc_txpowertrackingindex]); + rtl92e_set_bb_reg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, + dm_tx_bb_gain[priv->rfc_txpowertrackingindex]); RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc90 is %08x\n", dm_tx_bb_gain[priv->rfc_txpowertrackingindex]); RT_TRACE(COMP_POWER_TRACKING, @@ -1195,7 +1191,7 @@ static void dm_txpower_reset_recovery(struct net_device *dev) dm_tx_bb_gain_idx_to_amplify(priv->rfc_txpowertrackingindex)); } -void dm_restore_dynamic_mechanism_state(struct net_device *dev) +void rtl92e_dm_restore_state(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); u32 reg_ratr = priv->rate_adaptive.last_ratr; @@ -1203,7 +1199,7 @@ void dm_restore_dynamic_mechanism_state(struct net_device *dev) if (!priv->up) { RT_TRACE(COMP_RATE, - "<---- dm_restore_dynamic_mechanism_state(): driver is going to unload\n"); + "<---- rtl92e_dm_restore_state(): driver is going to unload\n"); return; } @@ -1215,8 +1211,8 @@ void dm_restore_dynamic_mechanism_state(struct net_device *dev) ratr_value = reg_ratr; if (priv->rf_type == RF_1T2R) ratr_value &= ~(RATE_ALL_OFDM_2SS); - write_nic_dword(dev, RATR0, ratr_value); - write_nic_byte(dev, UFWP, 1); + rtl92e_writel(dev, RATR0, ratr_value); + rtl92e_writeb(dev, UFWP, 1); if (priv->btxpower_trackingInit && priv->btxpower_tracking) dm_txpower_reset_recovery(dev); @@ -1232,18 +1228,18 @@ static void dm_bb_initialgain_restore(struct net_device *dev) if (dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) return; - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); - rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, bit_mask, - (u32)priv->initgain_backup.xaagccore1); - rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, bit_mask, - (u32)priv->initgain_backup.xbagccore1); - rtl8192_setBBreg(dev, rOFDM0_XCAGCCore1, bit_mask, - (u32)priv->initgain_backup.xcagccore1); - rtl8192_setBBreg(dev, rOFDM0_XDAGCCore1, bit_mask, - (u32)priv->initgain_backup.xdagccore1); + rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x8); + rtl92e_set_bb_reg(dev, rOFDM0_XAAGCCore1, bit_mask, + (u32)priv->initgain_backup.xaagccore1); + rtl92e_set_bb_reg(dev, rOFDM0_XBAGCCore1, bit_mask, + (u32)priv->initgain_backup.xbagccore1); + rtl92e_set_bb_reg(dev, rOFDM0_XCAGCCore1, bit_mask, + (u32)priv->initgain_backup.xcagccore1); + rtl92e_set_bb_reg(dev, rOFDM0_XDAGCCore1, bit_mask, + (u32)priv->initgain_backup.xdagccore1); bit_mask = bMaskByte2; - rtl8192_setBBreg(dev, rCCK0_CCA, bit_mask, - (u32)priv->initgain_backup.cca); + rtl92e_set_bb_reg(dev, rCCK0_CCA, bit_mask, + (u32)priv->initgain_backup.cca); RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc50 is %x\n", priv->initgain_backup.xaagccore1); @@ -1255,12 +1251,12 @@ static void dm_bb_initialgain_restore(struct net_device *dev) priv->initgain_backup.xdagccore1); RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xa0a is %x\n", priv->initgain_backup.cca); - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); + rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x1); } -void dm_backup_dynamic_mechanism_state(struct net_device *dev) +void rtl92e_dm_backup_state(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); @@ -1279,13 +1275,13 @@ static void dm_bb_initialgain_backup(struct net_device *dev) if (dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) return; - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); - priv->initgain_backup.xaagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XAAGCCore1, bit_mask); - priv->initgain_backup.xbagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XBAGCCore1, bit_mask); - priv->initgain_backup.xcagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XCAGCCore1, bit_mask); - priv->initgain_backup.xdagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XDAGCCore1, bit_mask); + rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x8); + priv->initgain_backup.xaagccore1 = (u8)rtl92e_get_bb_reg(dev, rOFDM0_XAAGCCore1, bit_mask); + priv->initgain_backup.xbagccore1 = (u8)rtl92e_get_bb_reg(dev, rOFDM0_XBAGCCore1, bit_mask); + priv->initgain_backup.xcagccore1 = (u8)rtl92e_get_bb_reg(dev, rOFDM0_XCAGCCore1, bit_mask); + priv->initgain_backup.xdagccore1 = (u8)rtl92e_get_bb_reg(dev, rOFDM0_XDAGCCore1, bit_mask); bit_mask = bMaskByte2; - priv->initgain_backup.cca = (u8)rtl8192_QueryBBReg(dev, rCCK0_CCA, bit_mask); + priv->initgain_backup.cca = (u8)rtl92e_get_bb_reg(dev, rCCK0_CCA, bit_mask); RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc50 is %x\n", priv->initgain_backup.xaagccore1); @@ -1376,7 +1372,7 @@ static void dm_ctrl_initgain_byrssi_by_driverrssi( fw_dig = 0; if (fw_dig <= 3) { for (i = 0; i < 3; i++) - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); + rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x8); fw_dig++; dm_digtable.dig_state = DM_STA_DIG_OFF; } @@ -1410,7 +1406,7 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( if (dm_digtable.dig_algorithm_switch) { dm_digtable.dig_state = DM_STA_DIG_MAX; for (i = 0; i < 3; i++) - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); + rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x1); dm_digtable.dig_algorithm_switch = 0; } @@ -1429,19 +1425,19 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( dm_digtable.dig_highpwr_state = DM_STA_DIG_MAX; dm_digtable.dig_state = DM_STA_DIG_OFF; - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); + rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x8); - write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x17); - write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x17); - write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x17); - write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x17); + rtl92e_writeb(dev, rOFDM0_XAAGCCore1, 0x17); + rtl92e_writeb(dev, rOFDM0_XBAGCCore1, 0x17); + rtl92e_writeb(dev, rOFDM0_XCAGCCore1, 0x17); + rtl92e_writeb(dev, rOFDM0_XDAGCCore1, 0x17); if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00); + rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x00); else - write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); + rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x42); - write_nic_byte(dev, 0xa0a, 0x08); + rtl92e_writeb(dev, 0xa0a, 0x08); return; } @@ -1462,25 +1458,25 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( dm_digtable.dig_state = DM_STA_DIG_ON; if (reset_flag == 1) { - write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x2c); - write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x2c); - write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x2c); - write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x2c); + rtl92e_writeb(dev, rOFDM0_XAAGCCore1, 0x2c); + rtl92e_writeb(dev, rOFDM0_XBAGCCore1, 0x2c); + rtl92e_writeb(dev, rOFDM0_XCAGCCore1, 0x2c); + rtl92e_writeb(dev, rOFDM0_XDAGCCore1, 0x2c); } else { - write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x20); - write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x20); - write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x20); - write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x20); + rtl92e_writeb(dev, rOFDM0_XAAGCCore1, 0x20); + rtl92e_writeb(dev, rOFDM0_XBAGCCore1, 0x20); + rtl92e_writeb(dev, rOFDM0_XCAGCCore1, 0x20); + rtl92e_writeb(dev, rOFDM0_XDAGCCore1, 0x20); } if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20); + rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x20); else - write_nic_byte(dev, rOFDM0_RxDetector1, 0x44); + rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x44); - write_nic_byte(dev, 0xa0a, 0xcd); + rtl92e_writeb(dev, 0xa0a, 0xcd); - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); + rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x1); } dm_ctrl_initgain_byrssi_highpwr(dev); } @@ -1505,9 +1501,9 @@ static void dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev) dm_digtable.dig_highpwr_state = DM_STA_DIG_ON; if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10); + rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x10); else - write_nic_byte(dev, rOFDM0_RxDetector1, 0x43); + rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x43); } else { if (dm_digtable.dig_highpwr_state == DM_STA_DIG_OFF && (priv->reset_count == reset_cnt_highpwr)) @@ -1519,9 +1515,9 @@ static void dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev) (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh)) { if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20); + rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x20); else - write_nic_byte(dev, rOFDM0_RxDetector1, 0x44); + rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x44); } } reset_cnt_highpwr = priv->reset_count; @@ -1568,16 +1564,16 @@ static void dm_initial_gain(struct net_device *dev) reset_cnt = priv->reset_count; } - if (dm_digtable.pre_ig_value != read_nic_byte(dev, rOFDM0_XAAGCCore1)) + if (dm_digtable.pre_ig_value != rtl92e_readb(dev, rOFDM0_XAAGCCore1)) force_write = 1; if ((dm_digtable.pre_ig_value != dm_digtable.cur_ig_value) || !initialized || force_write) { initial_gain = (u8)dm_digtable.cur_ig_value; - write_nic_byte(dev, rOFDM0_XAAGCCore1, initial_gain); - write_nic_byte(dev, rOFDM0_XBAGCCore1, initial_gain); - write_nic_byte(dev, rOFDM0_XCAGCCore1, initial_gain); - write_nic_byte(dev, rOFDM0_XDAGCCore1, initial_gain); + rtl92e_writeb(dev, rOFDM0_XAAGCCore1, initial_gain); + rtl92e_writeb(dev, rOFDM0_XBAGCCore1, initial_gain); + rtl92e_writeb(dev, rOFDM0_XCAGCCore1, initial_gain); + rtl92e_writeb(dev, rOFDM0_XDAGCCore1, initial_gain); dm_digtable.pre_ig_value = dm_digtable.cur_ig_value; initialized = 1; force_write = 0; @@ -1630,20 +1626,20 @@ static void dm_pd_th(struct net_device *dev) (initialized <= 3) || force_write) { if (dm_digtable.curpd_thstate == DIG_PD_AT_LOW_POWER) { if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00); + rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x00); else - write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); + rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x42); } else if (dm_digtable.curpd_thstate == DIG_PD_AT_NORMAL_POWER) { if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20); + rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x20); else - write_nic_byte(dev, rOFDM0_RxDetector1, 0x44); + rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x44); } else if (dm_digtable.curpd_thstate == DIG_PD_AT_HIGH_POWER) { if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10); + rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x10); else - write_nic_byte(dev, rOFDM0_RxDetector1, 0x43); + rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x43); } dm_digtable.prepd_thstate = dm_digtable.curpd_thstate; if (initialized <= 3) @@ -1687,16 +1683,16 @@ static void dm_cs_ratio(struct net_device *dev) if ((dm_digtable.precs_ratio_state != dm_digtable.curcs_ratio_state) || !initialized || force_write) { if (dm_digtable.curcs_ratio_state == DIG_CS_RATIO_LOWER) - write_nic_byte(dev, 0xa0a, 0x08); + rtl92e_writeb(dev, 0xa0a, 0x08); else if (dm_digtable.curcs_ratio_state == DIG_CS_RATIO_HIGHER) - write_nic_byte(dev, 0xa0a, 0xcd); + rtl92e_writeb(dev, 0xa0a, 0xcd); dm_digtable.precs_ratio_state = dm_digtable.curcs_ratio_state; initialized = 1; force_write = 0; } } -void dm_init_edca_turbo(struct net_device *dev) +void rtl92e_dm_init_edca_turbo(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); @@ -1745,21 +1741,19 @@ static void dm_check_edca_turbo(struct net_device *dev) if (curTxOkCnt > 4*curRxOkCnt) { if (priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) { - write_nic_dword(dev, EDCAPARA_BE, - edca_setting_UL[pHTInfo->IOTPeer]); + rtl92e_writel(dev, EDCAPARA_BE, + edca_setting_UL[pHTInfo->IOTPeer]); priv->bis_cur_rdlstate = false; } } else { if (!priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) { if (priv->rtllib->mode == WIRELESS_MODE_G) - write_nic_dword(dev, - EDCAPARA_BE, - edca_setting_DL_GMode[pHTInfo->IOTPeer]); + rtl92e_writel(dev, EDCAPARA_BE, + edca_setting_DL_GMode[pHTInfo->IOTPeer]); else - write_nic_dword(dev, - EDCAPARA_BE, - edca_setting_DL[pHTInfo->IOTPeer]); + rtl92e_writel(dev, EDCAPARA_BE, + edca_setting_DL[pHTInfo->IOTPeer]); priv->bis_cur_rdlstate = true; } } @@ -1769,20 +1763,18 @@ static void dm_check_edca_turbo(struct net_device *dev) if (!priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) { if (priv->rtllib->mode == WIRELESS_MODE_G) - write_nic_dword(dev, - EDCAPARA_BE, - edca_setting_DL_GMode[pHTInfo->IOTPeer]); + rtl92e_writel(dev, EDCAPARA_BE, + edca_setting_DL_GMode[pHTInfo->IOTPeer]); else - write_nic_dword(dev, - EDCAPARA_BE, - edca_setting_DL[pHTInfo->IOTPeer]); + rtl92e_writel(dev, EDCAPARA_BE, + edca_setting_DL[pHTInfo->IOTPeer]); priv->bis_cur_rdlstate = true; } } else { if (priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) { - write_nic_dword(dev, EDCAPARA_BE, - edca_setting_UL[pHTInfo->IOTPeer]); + rtl92e_writel(dev, EDCAPARA_BE, + edca_setting_UL[pHTInfo->IOTPeer]); priv->bis_cur_rdlstate = false; } @@ -1877,7 +1869,7 @@ static void dm_CheckRfCtrlGPIO(void *data) return; } - tmp1byte = read_nic_byte(dev, GPI); + tmp1byte = rtl92e_readb(dev, GPI); eRfPowerStateToSet = (tmp1byte&BIT1) ? eRfOn : eRfOff; @@ -1896,8 +1888,7 @@ static void dm_CheckRfCtrlGPIO(void *data) if (bActuallySet) { mdelay(1000); priv->bHwRfOffAction = 1; - MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW, - true); + rtl92e_set_rf_state(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW); if (priv->bHwRadioOff) argv[1] = "RFOFF"; else @@ -1909,7 +1900,7 @@ static void dm_CheckRfCtrlGPIO(void *data) } } -void dm_rf_pathcheck_workitemcallback(void *data) +void rtl92e_dm_rf_pathcheck_wq(void *data) { struct r8192_priv *priv = container_of_dwork_rsl(data, struct r8192_priv, @@ -1917,7 +1908,7 @@ void dm_rf_pathcheck_workitemcallback(void *data) struct net_device *dev = priv->rtllib->dev; u8 rfpath = 0, i; - rfpath = read_nic_byte(dev, 0xc04); + rfpath = rtl92e_readb(dev, 0xc04); for (i = 0; i < RF90_PATH_MAX; i++) { if (rfpath & (0x01<<i)) @@ -1974,12 +1965,12 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) return; if (!cck_Rx_Path_initialized) { - DM_RxPathSelTable.cck_Rx_path = (read_nic_byte(dev, 0xa07)&0xf); + DM_RxPathSelTable.cck_Rx_path = (rtl92e_readb(dev, 0xa07)&0xf); cck_Rx_Path_initialized = 1; } DM_RxPathSelTable.disabledRF = 0xf; - DM_RxPathSelTable.disabledRF &= ~(read_nic_byte(dev, 0xc04)); + DM_RxPathSelTable.disabledRF &= ~(rtl92e_readb(dev, 0xc04)); if (priv->rtllib->mode == WIRELESS_MODE_B) DM_RxPathSelTable.cck_method = CCK_Rx_Version_2; @@ -2116,10 +2107,10 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) DM_RxPathSelTable.diff_TH) { DM_RxPathSelTable.rf_enable_rssi_th[min_rssi_index] = tmp_max_rssi+5; - rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, - 0x1<<min_rssi_index, 0x0); - rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, - 0x1<<min_rssi_index, 0x0); + rtl92e_set_bb_reg(dev, rOFDM0_TRxPathEnable, + 0x1<<min_rssi_index, 0x0); + rtl92e_set_bb_reg(dev, rOFDM1_TRxPathEnable, + 0x1<<min_rssi_index, 0x0); disabled_rf_cnt++; } if (DM_RxPathSelTable.cck_method == CCK_Rx_Version_1) { @@ -2133,8 +2124,8 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) if (update_cck_rx_path) { DM_RxPathSelTable.cck_Rx_path = (cck_default_Rx<<2) | (cck_optional_Rx); - rtl8192_setBBreg(dev, rCCK0_AFESetting, 0x0f000000, - DM_RxPathSelTable.cck_Rx_path); + rtl92e_set_bb_reg(dev, rCCK0_AFESetting, 0x0f000000, + DM_RxPathSelTable.cck_Rx_path); } if (DM_RxPathSelTable.disabledRF) { @@ -2142,12 +2133,12 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) if ((DM_RxPathSelTable.disabledRF>>i) & 0x1) { if (tmp_max_rssi >= DM_RxPathSelTable.rf_enable_rssi_th[i]) { - rtl8192_setBBreg(dev, - rOFDM0_TRxPathEnable, 0x1 << i, - 0x1); - rtl8192_setBBreg(dev, - rOFDM1_TRxPathEnable, - 0x1 << i, 0x1); + rtl92e_set_bb_reg(dev, + rOFDM0_TRxPathEnable, + 0x1 << i, 0x1); + rtl92e_set_bb_reg(dev, + rOFDM1_TRxPathEnable, + 0x1 << i, 0x1); DM_RxPathSelTable.rf_enable_rssi_th[i] = 100; disabled_rf_cnt--; @@ -2252,18 +2243,18 @@ static void dm_fsync_timer_callback(unsigned long data) bDoubleTimeInterval = true; priv->bswitch_fsync = !priv->bswitch_fsync; if (priv->bswitch_fsync) { - write_nic_byte(dev, 0xC36, 0x1c); - write_nic_byte(dev, 0xC3e, 0x90); + rtl92e_writeb(dev, 0xC36, 0x1c); + rtl92e_writeb(dev, 0xC3e, 0x90); } else { - write_nic_byte(dev, 0xC36, 0x5c); - write_nic_byte(dev, 0xC3e, 0x96); + rtl92e_writeb(dev, 0xC36, 0x5c); + rtl92e_writeb(dev, 0xC3e, 0x96); } } else if (priv->undecorated_smoothed_pwdb <= priv->rtllib->fsync_rssi_threshold) { if (priv->bswitch_fsync) { priv->bswitch_fsync = false; - write_nic_byte(dev, 0xC36, 0x5c); - write_nic_byte(dev, 0xC3e, 0x96); + rtl92e_writeb(dev, 0xC36, 0x5c); + rtl92e_writeb(dev, 0xC3e, 0x96); } } if (bDoubleTimeInterval) { @@ -2283,11 +2274,11 @@ static void dm_fsync_timer_callback(unsigned long data) } else { if (priv->bswitch_fsync) { priv->bswitch_fsync = false; - write_nic_byte(dev, 0xC36, 0x5c); - write_nic_byte(dev, 0xC3e, 0x96); + rtl92e_writeb(dev, 0xC36, 0x5c); + rtl92e_writeb(dev, 0xC3e, 0x96); } priv->ContinueDiffCount = 0; - write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd); + rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c52cd); } RT_TRACE(COMP_HALDM, "ContinueDiffCount %d\n", priv->ContinueDiffCount); RT_TRACE(COMP_HALDM, @@ -2302,10 +2293,10 @@ static void dm_StartHWFsync(struct net_device *dev) struct r8192_priv *priv = rtllib_priv(dev); RT_TRACE(COMP_HALDM, "%s\n", __func__); - write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cf); + rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c12cf); priv->rtllib->SetHwRegHandler(dev, HW_VAR_RF_TIMING, (u8 *)(&rf_timing)); - write_nic_byte(dev, 0xc3b, 0x41); + rtl92e_writeb(dev, 0xc3b, 0x41); } static void dm_EndHWFsync(struct net_device *dev) @@ -2314,10 +2305,10 @@ static void dm_EndHWFsync(struct net_device *dev) struct r8192_priv *priv = rtllib_priv(dev); RT_TRACE(COMP_HALDM, "%s\n", __func__); - write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd); + rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c52cd); priv->rtllib->SetHwRegHandler(dev, HW_VAR_RF_TIMING, (u8 *) (&rf_timing)); - write_nic_byte(dev, 0xc3b, 0x49); + rtl92e_writeb(dev, 0xc3b, 0x49); } static void dm_EndSWFsync(struct net_device *dev) @@ -2330,13 +2321,13 @@ static void dm_EndSWFsync(struct net_device *dev) if (priv->bswitch_fsync) { priv->bswitch_fsync = false; - write_nic_byte(dev, 0xC36, 0x5c); + rtl92e_writeb(dev, 0xC36, 0x5c); - write_nic_byte(dev, 0xC3e, 0x96); + rtl92e_writeb(dev, 0xC3e, 0x96); } priv->ContinueDiffCount = 0; - write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd); + rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c52cd); } static void dm_StartSWFsync(struct net_device *dev) @@ -2371,7 +2362,7 @@ static void dm_StartSWFsync(struct net_device *dev) msecs_to_jiffies(priv->rtllib->fsync_time_interval); add_timer(&priv->fsync_timer); - write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cd); + rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c12cd); } @@ -2431,7 +2422,7 @@ static void dm_check_fsync(struct net_device *dev) } if (priv->framesyncMonitor) { if (reg_c38_State != RegC38_Fsync_AP_BCM) { - write_nic_byte(dev, rOFDM0_RxDetector3, 0x95); + rtl92e_writeb(dev, rOFDM0_RxDetector3, 0x95); reg_c38_State = RegC38_Fsync_AP_BCM; } @@ -2457,7 +2448,7 @@ static void dm_check_fsync(struct net_device *dev) RegC38_TH) { if (reg_c38_State != RegC38_NonFsync_Other_AP) { - write_nic_byte(dev, + rtl92e_writeb(dev, rOFDM0_RxDetector3, 0x90); @@ -2467,7 +2458,7 @@ static void dm_check_fsync(struct net_device *dev) } else if (priv->undecorated_smoothed_pwdb >= (RegC38_TH+5)) { if (reg_c38_State) { - write_nic_byte(dev, + rtl92e_writeb(dev, rOFDM0_RxDetector3, priv->framesync); reg_c38_State = RegC38_Default; @@ -2475,8 +2466,8 @@ static void dm_check_fsync(struct net_device *dev) } } else { if (reg_c38_State) { - write_nic_byte(dev, rOFDM0_RxDetector3, - priv->framesync); + rtl92e_writeb(dev, rOFDM0_RxDetector3, + priv->framesync); reg_c38_State = RegC38_Default; } } @@ -2484,14 +2475,14 @@ static void dm_check_fsync(struct net_device *dev) } if (priv->framesyncMonitor) { if (priv->reset_count != reset_cnt) { - write_nic_byte(dev, rOFDM0_RxDetector3, + rtl92e_writeb(dev, rOFDM0_RxDetector3, priv->framesync); reg_c38_State = RegC38_Default; reset_cnt = priv->reset_count; } } else { if (reg_c38_State) { - write_nic_byte(dev, rOFDM0_RxDetector3, + rtl92e_writeb(dev, rOFDM0_RxDetector3, priv->framesync); reg_c38_State = RegC38_Default; } @@ -2556,8 +2547,7 @@ static void dm_dynamic_txpower(struct net_device *dev) RT_TRACE(COMP_TXAGC, "SetTxPowerLevel8190() channel = %d\n", priv->rtllib->current_network.channel); - rtl8192_phy_setTxPower(dev, - priv->rtllib->current_network.channel); + rtl92e_set_tx_power(dev, priv->rtllib->current_network.channel); } priv->bLastDTPFlag_High = priv->bDynamicTxHighPower; priv->bLastDTPFlag_Low = priv->bDynamicTxLowPower; @@ -2569,13 +2559,13 @@ static void dm_check_txrateandretrycount(struct net_device *dev) struct r8192_priv *priv = rtllib_priv(dev); struct rtllib_device *ieee = priv->rtllib; - ieee->softmac_stats.CurrentShowTxate = read_nic_byte(dev, + ieee->softmac_stats.CurrentShowTxate = rtl92e_readb(dev, Current_Tx_Rate_Reg); - ieee->softmac_stats.last_packet_rate = read_nic_byte(dev, + ieee->softmac_stats.last_packet_rate = rtl92e_readb(dev, Initial_Tx_Rate_Reg); - ieee->softmac_stats.txretrycount = read_nic_dword(dev, + ieee->softmac_stats.txretrycount = rtl92e_readl(dev, Tx_Retry_Count_Reg); } @@ -2583,5 +2573,5 @@ static void dm_send_rssi_tofw(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); - write_nic_byte(dev, DRIVER_RSSI, (u8)priv->undecorated_smoothed_pwdb); + rtl92e_writeb(dev, DRIVER_RSSI, (u8)priv->undecorated_smoothed_pwdb); } diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.h b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.h index 95b8a8fd0556..e16502d12cdc 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.h @@ -188,20 +188,20 @@ extern const u8 dm_cck_tx_bb_gain_ch14[CCKTxBBGainTableLength][8]; /*--------------------------Exported Function prototype---------------------*/ /*--------------------------Exported Function prototype---------------------*/ -extern void init_hal_dm(struct net_device *dev); -extern void deinit_hal_dm(struct net_device *dev); +extern void rtl92e_dm_init(struct net_device *dev); +extern void rtl92e_dm_deinit(struct net_device *dev); -extern void hal_dm_watchdog(struct net_device *dev); +extern void rtl92e_dm_watchdog(struct net_device *dev); -extern void init_rate_adaptive(struct net_device *dev); -extern void dm_txpower_trackingcallback(void *data); +extern void rtl92e_init_adaptive_rate(struct net_device *dev); +extern void rtl92e_dm_txpower_tracking_wq(void *data); -extern void dm_cck_txpower_adjust(struct net_device *dev, bool binch14); +extern void rtl92e_dm_cck_txpower_adjust(struct net_device *dev, bool binch14); -extern void dm_restore_dynamic_mechanism_state(struct net_device *dev); -extern void dm_backup_dynamic_mechanism_state(struct net_device *dev); -extern void dm_init_edca_turbo(struct net_device *dev); -extern void dm_rf_pathcheck_workitemcallback(void *data); -extern void dm_initialize_txpower_tracking(struct net_device *dev); +extern void rtl92e_dm_restore_state(struct net_device *dev); +extern void rtl92e_dm_backup_state(struct net_device *dev); +extern void rtl92e_dm_init_edca_turbo(struct net_device *dev); +extern void rtl92e_dm_rf_pathcheck_wq(void *data); +extern void rtl92e_dm_init_txpower_tracking(struct net_device *dev); #endif /*__R8192UDM_H__ */ diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.c b/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.c index a6778e0853c7..039ccfd41230 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.c @@ -25,115 +25,75 @@ #include "rtl_core.h" #include "rtl_eeprom.h" -static void eprom_cs(struct net_device *dev, short bit) +static void _rtl92e_gpio_write_bit(struct net_device *dev, int no, bool val) { - if (bit) - write_nic_byte(dev, EPROM_CMD, - (1 << EPROM_CS_SHIFT) | - read_nic_byte(dev, EPROM_CMD)); + u8 reg = rtl92e_readb(dev, EPROM_CMD); + + if (val) + reg |= 1 << no; else - write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev, EPROM_CMD) - & ~(1<<EPROM_CS_SHIFT)); + reg &= ~(1 << no); + rtl92e_writeb(dev, EPROM_CMD, reg); udelay(EPROM_DELAY); } - -static void eprom_ck_cycle(struct net_device *dev) +static bool _rtl92e_gpio_get_bit(struct net_device *dev, int no) { - write_nic_byte(dev, EPROM_CMD, - (1<<EPROM_CK_SHIFT) | read_nic_byte(dev, EPROM_CMD)); - udelay(EPROM_DELAY); - write_nic_byte(dev, EPROM_CMD, - read_nic_byte(dev, EPROM_CMD) & ~(1<<EPROM_CK_SHIFT)); - udelay(EPROM_DELAY); -} + u8 reg = rtl92e_readb(dev, EPROM_CMD); + return (reg >> no) & 0x1; +} -static void eprom_w(struct net_device *dev, short bit) +static void _rtl92e_eeprom_ck_cycle(struct net_device *dev) { - if (bit) - write_nic_byte(dev, EPROM_CMD, (1<<EPROM_W_SHIFT) | - read_nic_byte(dev, EPROM_CMD)); - else - write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev, EPROM_CMD) - & ~(1<<EPROM_W_SHIFT)); - - udelay(EPROM_DELAY); + _rtl92e_gpio_write_bit(dev, EPROM_CK_BIT, 1); + _rtl92e_gpio_write_bit(dev, EPROM_CK_BIT, 0); } - -static short eprom_r(struct net_device *dev) +static u16 _rtl92e_eeprom_xfer(struct net_device *dev, u16 data, int tx_len) { - short bit; + u16 ret = 0; + int rx_len = 16; - bit = (read_nic_byte(dev, EPROM_CMD) & (1<<EPROM_R_SHIFT)); - udelay(EPROM_DELAY); + _rtl92e_gpio_write_bit(dev, EPROM_CS_BIT, 1); + _rtl92e_eeprom_ck_cycle(dev); - if (bit) - return 1; - return 0; -} + while (tx_len--) { + _rtl92e_gpio_write_bit(dev, EPROM_W_BIT, + (data >> tx_len) & 0x1); + _rtl92e_eeprom_ck_cycle(dev); + } -static void eprom_send_bits_string(struct net_device *dev, short b[], int len) -{ - int i; + _rtl92e_gpio_write_bit(dev, EPROM_W_BIT, 0); - for (i = 0; i < len; i++) { - eprom_w(dev, b[i]); - eprom_ck_cycle(dev); + while (rx_len--) { + _rtl92e_eeprom_ck_cycle(dev); + ret |= _rtl92e_gpio_get_bit(dev, EPROM_R_BIT) << rx_len; } + + _rtl92e_gpio_write_bit(dev, EPROM_CS_BIT, 0); + _rtl92e_eeprom_ck_cycle(dev); + + return ret; } -u32 eprom_read(struct net_device *dev, u32 addr) +u32 rtl92e_eeprom_read(struct net_device *dev, u32 addr) { struct r8192_priv *priv = rtllib_priv(dev); - short read_cmd[] = {1, 1, 0}; - short addr_str[8]; - int i; - int addr_len; - u32 ret; - - ret = 0; - write_nic_byte(dev, EPROM_CMD, - (EPROM_CMD_PROGRAM << EPROM_CMD_OPERATING_MODE_SHIFT)); - udelay(EPROM_DELAY); + u32 ret = 0; - if (priv->epromtype == EEPROM_93C56) { - addr_str[7] = addr & 1; - addr_str[6] = addr & (1<<1); - addr_str[5] = addr & (1<<2); - addr_str[4] = addr & (1<<3); - addr_str[3] = addr & (1<<4); - addr_str[2] = addr & (1<<5); - addr_str[1] = addr & (1<<6); - addr_str[0] = addr & (1<<7); - addr_len = 8; - } else { - addr_str[5] = addr & 1; - addr_str[4] = addr & (1<<1); - addr_str[3] = addr & (1<<2); - addr_str[2] = addr & (1<<3); - addr_str[1] = addr & (1<<4); - addr_str[0] = addr & (1<<5); - addr_len = 6; - } - eprom_cs(dev, 1); - eprom_ck_cycle(dev); - eprom_send_bits_string(dev, read_cmd, 3); - eprom_send_bits_string(dev, addr_str, addr_len); - - eprom_w(dev, 0); - - for (i = 0; i < 16; i++) { - eprom_ck_cycle(dev); - ret |= (eprom_r(dev)<<(15-i)); - } + rtl92e_writeb(dev, EPROM_CMD, + (EPROM_CMD_PROGRAM << EPROM_CMD_OPERATING_MODE_SHIFT)); + udelay(EPROM_DELAY); - eprom_cs(dev, 0); - eprom_ck_cycle(dev); + /* EEPROM is configured as x16 */ + if (priv->epromtype == EEPROM_93C56) + ret = _rtl92e_eeprom_xfer(dev, (addr & 0xFF) | (0x6 << 8), 11); + else + ret = _rtl92e_eeprom_xfer(dev, (addr & 0x3F) | (0x6 << 6), 9); - write_nic_byte(dev, EPROM_CMD, - (EPROM_CMD_NORMAL<<EPROM_CMD_OPERATING_MODE_SHIFT)); + rtl92e_writeb(dev, EPROM_CMD, + (EPROM_CMD_NORMAL<<EPROM_CMD_OPERATING_MODE_SHIFT)); return ret; } diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.h b/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.h index adea2b4c7a44..8d23aea5fb4f 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.h @@ -26,4 +26,4 @@ #define EPROM_DELAY 10 -u32 eprom_read(struct net_device *dev, u32 addr); +u32 rtl92e_eeprom_read(struct net_device *dev, u32 addr); diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pci.c b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.c index 6bbd1c626e24..9fcb099e6edd 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_pci.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.c @@ -45,7 +45,7 @@ static void rtl8192_parse_pci_configuration(struct pci_dev *pdev, pci_write_config_byte(pdev, 0x70f, tmp); } -bool rtl8192_pci_findadapter(struct pci_dev *pdev, struct net_device *dev) +bool rtl92e_check_adapter(struct pci_dev *pdev, struct net_device *dev) { struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); u16 VenderID; diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h index e8d5527a5f04..6246841bde15 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h @@ -29,6 +29,6 @@ #include <linux/pci.h> struct net_device; -bool rtl8192_pci_findadapter(struct pci_dev *pdev, struct net_device *dev); +bool rtl92e_check_adapter(struct pci_dev *pdev, struct net_device *dev); #endif diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c index e4908672421c..b0268fdc100f 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c @@ -23,7 +23,7 @@ #include "rtl_pm.h" -int rtl8192E_suspend(struct pci_dev *pdev, pm_message_t state) +int rtl92e_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *dev = pci_get_drvdata(pdev); struct r8192_priv *priv = rtllib_priv(dev); @@ -45,16 +45,16 @@ int rtl8192E_suspend(struct pci_dev *pdev, pm_message_t state) netif_device_detach(dev); if (!priv->rtllib->bSupportRemoteWakeUp) { - MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_INIT, true); - ulRegRead = read_nic_dword(dev, CPU_GEN); + rtl92e_set_rf_state(dev, eRfOff, RF_CHANGE_BY_INIT); + ulRegRead = rtl92e_readl(dev, CPU_GEN); ulRegRead |= CPU_GEN_SYSTEM_RESET; - write_nic_dword(dev, CPU_GEN, ulRegRead); + rtl92e_writel(dev, CPU_GEN, ulRegRead); } else { - write_nic_dword(dev, WFCRC0, 0xffffffff); - write_nic_dword(dev, WFCRC1, 0xffffffff); - write_nic_dword(dev, WFCRC2, 0xffffffff); - write_nic_byte(dev, PMR, 0x5); - write_nic_byte(dev, MacBlkCtrl, 0xa); + rtl92e_writel(dev, WFCRC0, 0xffffffff); + rtl92e_writel(dev, WFCRC1, 0xffffffff); + rtl92e_writel(dev, WFCRC2, 0xffffffff); + rtl92e_writeb(dev, PMR, 0x5); + rtl92e_writeb(dev, MacBlkCtrl, 0xa); } out_pci_suspend: netdev_info(dev, "WOL is %s\n", priv->rtllib->bSupportRemoteWakeUp ? @@ -70,7 +70,7 @@ out_pci_suspend: return 0; } -int rtl8192E_resume(struct pci_dev *pdev) +int rtl92e_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct r8192_priv *priv = rtllib_priv(dev); @@ -95,7 +95,7 @@ int rtl8192E_resume(struct pci_dev *pdev) pci_enable_wake(pdev, PCI_D0, 0); if (priv->polling_timer_on == 0) - check_rfctrl_gpio_timer((unsigned long)dev); + rtl92e_check_rfctrl_gpio_timer((unsigned long)dev); if (!netif_running(dev)) { netdev_info(dev, @@ -108,7 +108,7 @@ int rtl8192E_resume(struct pci_dev *pdev) dev->netdev_ops->ndo_open(dev); if (!priv->rtllib->bSupportRemoteWakeUp) - MgntActSet_RF_State(dev, eRfOn, RF_CHANGE_BY_INIT, true); + rtl92e_set_rf_state(dev, eRfOn, RF_CHANGE_BY_INIT); out: RT_TRACE(COMP_POWER, "<================r8192E resume call.\n"); diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h index 7bfe44817f23..cdc45f7fb339 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h @@ -23,7 +23,7 @@ #include <linux/types.h> #include <linux/pci.h> -int rtl8192E_suspend(struct pci_dev *dev, pm_message_t state); -int rtl8192E_resume(struct pci_dev *dev); +int rtl92e_suspend(struct pci_dev *dev, pm_message_t state); +int rtl92e_resume(struct pci_dev *dev); #endif diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c index 404cb83153d9..f09560d60dc4 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c @@ -45,10 +45,10 @@ static void rtl8192_hw_sleep_down(struct net_device *dev) spin_unlock_irqrestore(&priv->rf_ps_lock, flags); RT_TRACE(COMP_DBG, "%s()============>come to sleep down\n", __func__); - MgntActSet_RF_State(dev, eRfSleep, RF_CHANGE_BY_PS, false); + rtl92e_set_rf_state(dev, eRfSleep, RF_CHANGE_BY_PS); } -void rtl8192_hw_sleep_wq(void *data) +void rtl92e_hw_sleep_wq(void *data) { struct rtllib_device *ieee = container_of_dwork_rsl(data, struct rtllib_device, hw_sleep_wq); @@ -57,7 +57,7 @@ void rtl8192_hw_sleep_wq(void *data) rtl8192_hw_sleep_down(dev); } -void rtl8192_hw_wakeup(struct net_device *dev) +void rtl92e_hw_wakeup(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); unsigned long flags = 0; @@ -66,7 +66,7 @@ void rtl8192_hw_wakeup(struct net_device *dev) if (priv->RFChangeInProgress) { spin_unlock_irqrestore(&priv->rf_ps_lock, flags); RT_TRACE(COMP_DBG, - "rtl8192_hw_wakeup(): RF Change in progress!\n"); + "rtl92e_hw_wakeup(): RF Change in progress!\n"); queue_delayed_work_rsl(priv->rtllib->wq, &priv->rtllib->hw_wakeup_wq, msecs_to_jiffies(10)); @@ -74,21 +74,21 @@ void rtl8192_hw_wakeup(struct net_device *dev) } spin_unlock_irqrestore(&priv->rf_ps_lock, flags); RT_TRACE(COMP_PS, "%s()============>come to wake up\n", __func__); - MgntActSet_RF_State(dev, eRfOn, RF_CHANGE_BY_PS, false); + rtl92e_set_rf_state(dev, eRfOn, RF_CHANGE_BY_PS); } -void rtl8192_hw_wakeup_wq(void *data) +void rtl92e_hw_wakeup_wq(void *data) { struct rtllib_device *ieee = container_of_dwork_rsl(data, struct rtllib_device, hw_wakeup_wq); struct net_device *dev = ieee->dev; - rtl8192_hw_wakeup(dev); + rtl92e_hw_wakeup(dev); } #define MIN_SLEEP_TIME 50 #define MAX_SLEEP_TIME 10000 -void rtl8192_hw_to_sleep(struct net_device *dev, u64 time) +void rtl92e_enter_sleep(struct net_device *dev, u64 time) { struct r8192_priv *priv = rtllib_priv(dev); @@ -133,14 +133,13 @@ static void InactivePsWorkItemCallback(struct net_device *dev) RT_TRACE(COMP_PS, "InactivePsWorkItemCallback(): Set RF to %s.\n", pPSC->eInactivePowerState == eRfOff ? "OFF" : "ON"); - MgntActSet_RF_State(dev, pPSC->eInactivePowerState, RF_CHANGE_BY_IPS, - false); + rtl92e_set_rf_state(dev, pPSC->eInactivePowerState, RF_CHANGE_BY_IPS); pPSC->bSwRfProcessing = false; RT_TRACE(COMP_PS, "InactivePsWorkItemCallback() <---------\n"); } -void IPSEnter(struct net_device *dev) +void rtl92e_ips_enter(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *) @@ -152,7 +151,7 @@ void IPSEnter(struct net_device *dev) if (rtState == eRfOn && !pPSC->bSwRfProcessing && (priv->rtllib->state != RTLLIB_LINKED) && (priv->rtllib->iw_mode != IW_MODE_MASTER)) { - RT_TRACE(COMP_PS, "IPSEnter(): Turn off RF.\n"); + RT_TRACE(COMP_PS, "rtl92e_ips_enter(): Turn off RF.\n"); pPSC->eInactivePowerState = eRfOff; priv->isRFOff = true; priv->bInPowerSaveMode = true; @@ -161,7 +160,7 @@ void IPSEnter(struct net_device *dev) } } -void IPSLeave(struct net_device *dev) +void rtl92e_ips_leave(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *) @@ -172,7 +171,7 @@ void IPSLeave(struct net_device *dev) rtState = priv->rtllib->eRFPowerState; if (rtState != eRfOn && !pPSC->bSwRfProcessing && priv->rtllib->RfOffReason <= RF_CHANGE_BY_IPS) { - RT_TRACE(COMP_PS, "IPSLeave(): Turn on RF.\n"); + RT_TRACE(COMP_PS, "rtl92e_ips_leave(): Turn on RF.\n"); pPSC->eInactivePowerState = eRfOn; priv->bInPowerSaveMode = false; InactivePsWorkItemCallback(dev); @@ -180,7 +179,7 @@ void IPSLeave(struct net_device *dev) } } -void IPSLeave_wq(void *data) +void rtl92e_ips_leave_wq(void *data) { struct rtllib_device *ieee = container_of_work_rsl(data, struct rtllib_device, ips_leave_wq); @@ -188,11 +187,11 @@ void IPSLeave_wq(void *data) struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); down(&priv->rtllib->ips_sem); - IPSLeave(dev); + rtl92e_ips_leave(dev); up(&priv->rtllib->ips_sem); } -void rtllib_ips_leave_wq(struct net_device *dev) +void rtl92e_rtllib_ips_leave_wq(struct net_device *dev) { struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); enum rt_rf_power_state rtState; @@ -206,7 +205,7 @@ void rtllib_ips_leave_wq(struct net_device *dev) __func__); return; } - netdev_info(dev, "=========>%s(): IPSLeave\n", + netdev_info(dev, "=========>%s(): rtl92e_ips_leave\n", __func__); queue_work_rsl(priv->rtllib->wq, &priv->rtllib->ips_leave_wq); @@ -214,12 +213,12 @@ void rtllib_ips_leave_wq(struct net_device *dev) } } -void rtllib_ips_leave(struct net_device *dev) +void rtl92e_rtllib_ips_leave(struct net_device *dev) { struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); down(&priv->rtllib->ips_sem); - IPSLeave(dev); + rtl92e_ips_leave(dev); up(&priv->rtllib->ips_sem); } @@ -238,7 +237,7 @@ static bool MgntActSet_802_11_PowerSaveMode(struct net_device *dev, rtPsMode == RTLLIB_PS_DISABLED) { unsigned long flags; - rtl8192_hw_wakeup(dev); + rtl92e_hw_wakeup(dev); priv->rtllib->sta_sleep = LPS_IS_WAKE; spin_lock_irqsave(&(priv->rtllib->mgmt_tx_lock), flags); @@ -251,13 +250,13 @@ static bool MgntActSet_802_11_PowerSaveMode(struct net_device *dev, return true; } -void LeisurePSEnter(struct net_device *dev) +void rtl92e_leisure_ps_enter(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *) &(priv->rtllib->PowerSaveControl); - RT_TRACE(COMP_PS, "LeisurePSEnter()...\n"); + RT_TRACE(COMP_PS, "rtl92e_leisure_ps_enter()...\n"); RT_TRACE(COMP_PS, "pPSC->bLeisurePs = %d, ieee->ps = %d,pPSC->LpsIdleCount is %d,RT_CHECK_FOR_HANG_PERIOD is %d\n", pPSC->bLeisurePs, priv->rtllib->ps, pPSC->LpsIdleCount, @@ -275,7 +274,7 @@ void LeisurePSEnter(struct net_device *dev) if (priv->rtllib->ps == RTLLIB_PS_DISABLED) { RT_TRACE(COMP_LPS, - "LeisurePSEnter(): Enter 802.11 power save mode...\n"); + "rtl92e_leisure_ps_enter(): Enter 802.11 power save mode...\n"); if (!pPSC->bFwCtrlLPS) { if (priv->rtllib->SetFwCmdHandler) @@ -291,21 +290,21 @@ void LeisurePSEnter(struct net_device *dev) } } -void LeisurePSLeave(struct net_device *dev) +void rtl92e_leisure_ps_leave(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *) &(priv->rtllib->PowerSaveControl); - RT_TRACE(COMP_PS, "LeisurePSLeave()...\n"); + RT_TRACE(COMP_PS, "rtl92e_leisure_ps_leave()...\n"); RT_TRACE(COMP_PS, "pPSC->bLeisurePs = %d, ieee->ps = %d\n", pPSC->bLeisurePs, priv->rtllib->ps); if (pPSC->bLeisurePs) { if (priv->rtllib->ps != RTLLIB_PS_DISABLED) { RT_TRACE(COMP_LPS, - "LeisurePSLeave(): Busy Traffic , Leave 802.11 power save..\n"); + "rtl92e_leisure_ps_leave(): Busy Traffic , Leave 802.11 power save..\n"); MgntActSet_802_11_PowerSaveMode(dev, RTLLIB_PS_DISABLED); diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.h b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.h index d23c0f1d76f5..35fc9e2a3365 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.h @@ -31,16 +31,16 @@ struct net_device; #define RT_CHECK_FOR_HANG_PERIOD 2 -void rtl8192_hw_wakeup(struct net_device *dev); -void rtl8192_hw_to_sleep(struct net_device *dev, u64 time); -void rtllib_ips_leave_wq(struct net_device *dev); -void rtllib_ips_leave(struct net_device *dev); -void IPSLeave_wq(void *data); +void rtl92e_hw_wakeup(struct net_device *dev); +void rtl92e_enter_sleep(struct net_device *dev, u64 time); +void rtl92e_rtllib_ips_leave_wq(struct net_device *dev); +void rtl92e_rtllib_ips_leave(struct net_device *dev); +void rtl92e_ips_leave_wq(void *data); -void IPSEnter(struct net_device *dev); -void IPSLeave(struct net_device *dev); +void rtl92e_ips_enter(struct net_device *dev); +void rtl92e_ips_leave(struct net_device *dev); -void LeisurePSEnter(struct net_device *dev); -void LeisurePSLeave(struct net_device *dev); +void rtl92e_leisure_ps_enter(struct net_device *dev); +void rtl92e_leisure_ps_leave(struct net_device *dev); #endif diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c index 15fc48440cdc..7e3ca7ef997b 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c @@ -192,7 +192,7 @@ static int r8192_wx_adapter_power_status(struct net_device *dev, pPSC->bLeisurePs = true; } else { if (priv->rtllib->state == RTLLIB_LINKED) - LeisurePSLeave(dev); + rtl92e_leisure_ps_leave(dev); priv->ps_force = true; pPSC->bLeisurePs = false; @@ -282,10 +282,11 @@ static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a, up(&priv->wx_sem); return -1; } - netdev_info(dev, "=========>%s(): IPSLeave\n", + netdev_info(dev, + "=========>%s(): rtl92e_ips_leave\n", __func__); down(&priv->rtllib->ips_sem); - IPSLeave(dev); + rtl92e_ips_leave(dev); up(&priv->rtllib->ips_sem); } } @@ -442,10 +443,11 @@ static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a, up(&priv->wx_sem); return -1; } - RT_TRACE(COMP_PS, "=========>%s(): IPSLeave\n", + RT_TRACE(COMP_PS, + "=========>%s(): rtl92e_ips_leave\n", __func__); down(&priv->rtllib->ips_sem); - IPSLeave(dev); + rtl92e_ips_leave(dev); up(&priv->rtllib->ips_sem); } } @@ -700,7 +702,7 @@ static int r8192_wx_set_enc(struct net_device *dev, priv->rtllib->wx_set_enc = 1; down(&priv->rtllib->ips_sem); - IPSLeave(dev); + rtl92e_ips_leave(dev); up(&priv->rtllib->ips_sem); down(&priv->wx_sem); @@ -711,7 +713,7 @@ static int r8192_wx_set_enc(struct net_device *dev, if (wrqu->encoding.flags & IW_ENCODE_DISABLED) { ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA; - CamResetAllEntry(dev); + rtl92e_cam_reset(dev); memset(priv->rtllib->swcamtable, 0, sizeof(struct sw_cam_table) * 32); goto end_hw_sec; @@ -750,16 +752,16 @@ static int r8192_wx_set_enc(struct net_device *dev, } if (wrqu->encoding.length == 0x5) { ieee->pairwise_key_type = KEY_TYPE_WEP40; - EnableHWSecurityConfig8192(dev); + rtl92e_enable_hw_security_config(dev); } else if (wrqu->encoding.length == 0xd) { ieee->pairwise_key_type = KEY_TYPE_WEP104; - EnableHWSecurityConfig8192(dev); - setKey(dev, key_idx, key_idx, KEY_TYPE_WEP104, - zero_addr[key_idx], 0, hwkey); - set_swcam(dev, key_idx, key_idx, KEY_TYPE_WEP104, - zero_addr[key_idx], 0, hwkey, 0); + rtl92e_enable_hw_security_config(dev); + rtl92e_set_key(dev, key_idx, key_idx, KEY_TYPE_WEP104, + zero_addr[key_idx], 0, hwkey); + rtl92e_set_swcam(dev, key_idx, key_idx, KEY_TYPE_WEP104, + zero_addr[key_idx], 0, hwkey, 0); } else { netdev_info(dev, "wrong type in WEP, not WEP40 and WEP104\n"); @@ -824,7 +826,7 @@ static int r8192_wx_set_retry(struct net_device *dev, } - rtl8192_commit(dev); + rtl92e_commit(dev); exit: up(&priv->wx_sem); @@ -910,7 +912,7 @@ static int r8192_wx_set_enc_ext(struct net_device *dev, priv->rtllib->wx_set_enc = 1; down(&priv->rtllib->ips_sem); - IPSLeave(dev); + rtl92e_ips_leave(dev); up(&priv->rtllib->ips_sem); ret = rtllib_wx_set_encode_ext(ieee, info, wrqu, extra); @@ -926,7 +928,7 @@ static int r8192_wx_set_enc_ext(struct net_device *dev, ext->alg == IW_ENCODE_ALG_NONE) { ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA; - CamResetAllEntry(dev); + rtl92e_cam_reset(dev); memset(priv->rtllib->swcamtable, 0, sizeof(struct sw_cam_table) * 32); goto end_hw_sec; @@ -943,28 +945,29 @@ static int r8192_wx_set_enc_ext(struct net_device *dev, if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40)) alg = KEY_TYPE_WEP104; ieee->pairwise_key_type = alg; - EnableHWSecurityConfig8192(dev); + rtl92e_enable_hw_security_config(dev); } memcpy((u8 *)key, ext->key, 16); if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode != 2)) { if (ext->key_len == 13) ieee->pairwise_key_type = alg = KEY_TYPE_WEP104; - setKey(dev, idx, idx, alg, zero, 0, key); - set_swcam(dev, idx, idx, alg, zero, 0, key, 0); + rtl92e_set_key(dev, idx, idx, alg, zero, 0, key); + rtl92e_set_swcam(dev, idx, idx, alg, zero, 0, key, 0); } else if (group) { ieee->group_key_type = alg; - setKey(dev, idx, idx, alg, broadcast_addr, 0, key); - set_swcam(dev, idx, idx, alg, broadcast_addr, 0, - key, 0); + rtl92e_set_key(dev, idx, idx, alg, broadcast_addr, 0, + key); + rtl92e_set_swcam(dev, idx, idx, alg, broadcast_addr, 0, + key, 0); } else { if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport) - write_nic_byte(dev, 0x173, 1); - setKey(dev, 4, idx, alg, (u8 *)ieee->ap_mac_addr, - 0, key); - set_swcam(dev, 4, idx, alg, (u8 *)ieee->ap_mac_addr, - 0, key, 0); + rtl92e_writeb(dev, 0x173, 1); + rtl92e_set_key(dev, 4, idx, alg, + (u8 *)ieee->ap_mac_addr, 0, key); + rtl92e_set_swcam(dev, 4, idx, alg, + (u8 *)ieee->ap_mac_addr, 0, key, 0); } @@ -1112,41 +1115,41 @@ static int r8192_wx_get_PromiscuousMode(struct net_device *dev, } -#define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT] +#define IW_IOCTL(x) ((x) - SIOCSIWCOMMIT) static iw_handler r8192_wx_handlers[] = { - IW_IOCTL(SIOCGIWNAME) = r8192_wx_get_name, - IW_IOCTL(SIOCSIWFREQ) = r8192_wx_set_freq, - IW_IOCTL(SIOCGIWFREQ) = r8192_wx_get_freq, - IW_IOCTL(SIOCSIWMODE) = r8192_wx_set_mode, - IW_IOCTL(SIOCGIWMODE) = r8192_wx_get_mode, - IW_IOCTL(SIOCSIWSENS) = r8192_wx_set_sens, - IW_IOCTL(SIOCGIWSENS) = r8192_wx_get_sens, - IW_IOCTL(SIOCGIWRANGE) = rtl8192_wx_get_range, - IW_IOCTL(SIOCSIWAP) = r8192_wx_set_wap, - IW_IOCTL(SIOCGIWAP) = r8192_wx_get_wap, - IW_IOCTL(SIOCSIWSCAN) = r8192_wx_set_scan, - IW_IOCTL(SIOCGIWSCAN) = r8192_wx_get_scan, - IW_IOCTL(SIOCSIWESSID) = r8192_wx_set_essid, - IW_IOCTL(SIOCGIWESSID) = r8192_wx_get_essid, - IW_IOCTL(SIOCSIWNICKN) = r8192_wx_set_nick, - IW_IOCTL(SIOCGIWNICKN) = r8192_wx_get_nick, - IW_IOCTL(SIOCSIWRATE) = r8192_wx_set_rate, - IW_IOCTL(SIOCGIWRATE) = r8192_wx_get_rate, - IW_IOCTL(SIOCSIWRTS) = r8192_wx_set_rts, - IW_IOCTL(SIOCGIWRTS) = r8192_wx_get_rts, - IW_IOCTL(SIOCSIWFRAG) = r8192_wx_set_frag, - IW_IOCTL(SIOCGIWFRAG) = r8192_wx_get_frag, - IW_IOCTL(SIOCSIWRETRY) = r8192_wx_set_retry, - IW_IOCTL(SIOCGIWRETRY) = r8192_wx_get_retry, - IW_IOCTL(SIOCSIWENCODE) = r8192_wx_set_enc, - IW_IOCTL(SIOCGIWENCODE) = r8192_wx_get_enc, - IW_IOCTL(SIOCSIWPOWER) = r8192_wx_set_power, - IW_IOCTL(SIOCGIWPOWER) = r8192_wx_get_power, - IW_IOCTL(SIOCSIWGENIE) = r8192_wx_set_gen_ie, - IW_IOCTL(SIOCGIWGENIE) = r8192_wx_get_gen_ie, - IW_IOCTL(SIOCSIWMLME) = r8192_wx_set_mlme, - IW_IOCTL(SIOCSIWAUTH) = r8192_wx_set_auth, - IW_IOCTL(SIOCSIWENCODEEXT) = r8192_wx_set_enc_ext, + [IW_IOCTL(SIOCGIWNAME)] = r8192_wx_get_name, + [IW_IOCTL(SIOCSIWFREQ)] = r8192_wx_set_freq, + [IW_IOCTL(SIOCGIWFREQ)] = r8192_wx_get_freq, + [IW_IOCTL(SIOCSIWMODE)] = r8192_wx_set_mode, + [IW_IOCTL(SIOCGIWMODE)] = r8192_wx_get_mode, + [IW_IOCTL(SIOCSIWSENS)] = r8192_wx_set_sens, + [IW_IOCTL(SIOCGIWSENS)] = r8192_wx_get_sens, + [IW_IOCTL(SIOCGIWRANGE)] = rtl8192_wx_get_range, + [IW_IOCTL(SIOCSIWAP)] = r8192_wx_set_wap, + [IW_IOCTL(SIOCGIWAP)] = r8192_wx_get_wap, + [IW_IOCTL(SIOCSIWSCAN)] = r8192_wx_set_scan, + [IW_IOCTL(SIOCGIWSCAN)] = r8192_wx_get_scan, + [IW_IOCTL(SIOCSIWESSID)] = r8192_wx_set_essid, + [IW_IOCTL(SIOCGIWESSID)] = r8192_wx_get_essid, + [IW_IOCTL(SIOCSIWNICKN)] = r8192_wx_set_nick, + [IW_IOCTL(SIOCGIWNICKN)] = r8192_wx_get_nick, + [IW_IOCTL(SIOCSIWRATE)] = r8192_wx_set_rate, + [IW_IOCTL(SIOCGIWRATE)] = r8192_wx_get_rate, + [IW_IOCTL(SIOCSIWRTS)] = r8192_wx_set_rts, + [IW_IOCTL(SIOCGIWRTS)] = r8192_wx_get_rts, + [IW_IOCTL(SIOCSIWFRAG)] = r8192_wx_set_frag, + [IW_IOCTL(SIOCGIWFRAG)] = r8192_wx_get_frag, + [IW_IOCTL(SIOCSIWRETRY)] = r8192_wx_set_retry, + [IW_IOCTL(SIOCGIWRETRY)] = r8192_wx_get_retry, + [IW_IOCTL(SIOCSIWENCODE)] = r8192_wx_set_enc, + [IW_IOCTL(SIOCGIWENCODE)] = r8192_wx_get_enc, + [IW_IOCTL(SIOCSIWPOWER)] = r8192_wx_set_power, + [IW_IOCTL(SIOCGIWPOWER)] = r8192_wx_get_power, + [IW_IOCTL(SIOCSIWGENIE)] = r8192_wx_set_gen_ie, + [IW_IOCTL(SIOCGIWGENIE)] = r8192_wx_get_gen_ie, + [IW_IOCTL(SIOCSIWMLME)] = r8192_wx_set_mlme, + [IW_IOCTL(SIOCSIWAUTH)] = r8192_wx_set_auth, + [IW_IOCTL(SIOCSIWENCODEEXT)] = r8192_wx_set_enc_ext, }; /* the following rule need to be following, diff --git a/drivers/staging/rtl8192e/rtl819x_BAProc.c b/drivers/staging/rtl8192e/rtl819x_BAProc.c index 60f536c295ab..78ede4a817fc 100644 --- a/drivers/staging/rtl8192e/rtl819x_BAProc.c +++ b/drivers/staging/rtl8192e/rtl819x_BAProc.c @@ -428,7 +428,6 @@ int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb) { struct rtllib_hdr_3addr *delba = NULL; union delba_param_set *pDelBaParamSet = NULL; - u16 *pReasonCode = NULL; u8 *dst = NULL; if (skb->len < sizeof(struct rtllib_hdr_3addr) + 6) { @@ -453,9 +452,7 @@ int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb) #endif delba = (struct rtllib_hdr_3addr *)skb->data; dst = (u8 *)(&delba->addr2[0]); - delba += sizeof(struct rtllib_hdr_3addr); - pDelBaParamSet = (union delba_param_set *)(delba+2); - pReasonCode = (u16 *)(delba+4); + pDelBaParamSet = (union delba_param_set *)&delba->payload[2]; if (pDelBaParamSet->field.Initiator == 1) { struct rx_ts_record *pRxTs; diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index 54dfff61f485..09f0820fb340 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -1744,37 +1744,61 @@ static int rtllib_parse_qos_info_param_IE(struct rtllib_device *ieee, return rc; } -#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x - static const char *get_info_element_string(u16 id) { switch (id) { - MFIE_STRING(SSID); - MFIE_STRING(RATES); - MFIE_STRING(FH_SET); - MFIE_STRING(DS_SET); - MFIE_STRING(CF_SET); - MFIE_STRING(TIM); - MFIE_STRING(IBSS_SET); - MFIE_STRING(COUNTRY); - MFIE_STRING(HOP_PARAMS); - MFIE_STRING(HOP_TABLE); - MFIE_STRING(REQUEST); - MFIE_STRING(CHALLENGE); - MFIE_STRING(POWER_CONSTRAINT); - MFIE_STRING(POWER_CAPABILITY); - MFIE_STRING(TPC_REQUEST); - MFIE_STRING(TPC_REPORT); - MFIE_STRING(SUPP_CHANNELS); - MFIE_STRING(CSA); - MFIE_STRING(MEASURE_REQUEST); - MFIE_STRING(MEASURE_REPORT); - MFIE_STRING(QUIET); - MFIE_STRING(IBSS_DFS); - MFIE_STRING(RSN); - MFIE_STRING(RATES_EX); - MFIE_STRING(GENERIC); - MFIE_STRING(QOS_PARAMETER); + case MFIE_TYPE_SSID: + return "SSID"; + case MFIE_TYPE_RATES: + return "RATES"; + case MFIE_TYPE_FH_SET: + return "FH_SET"; + case MFIE_TYPE_DS_SET: + return "DS_SET"; + case MFIE_TYPE_CF_SET: + return "CF_SET"; + case MFIE_TYPE_TIM: + return "TIM"; + case MFIE_TYPE_IBSS_SET: + return "IBSS_SET"; + case MFIE_TYPE_COUNTRY: + return "COUNTRY"; + case MFIE_TYPE_HOP_PARAMS: + return "HOP_PARAMS"; + case MFIE_TYPE_HOP_TABLE: + return "HOP_TABLE"; + case MFIE_TYPE_REQUEST: + return "REQUEST"; + case MFIE_TYPE_CHALLENGE: + return "CHALLENGE"; + case MFIE_TYPE_POWER_CONSTRAINT: + return "POWER_CONSTRAINT"; + case MFIE_TYPE_POWER_CAPABILITY: + return "POWER_CAPABILITY"; + case MFIE_TYPE_TPC_REQUEST: + return "TPC_REQUEST"; + case MFIE_TYPE_TPC_REPORT: + return "TPC_REPORT"; + case MFIE_TYPE_SUPP_CHANNELS: + return "SUPP_CHANNELS"; + case MFIE_TYPE_CSA: + return "CSA"; + case MFIE_TYPE_MEASURE_REQUEST: + return "MEASURE_REQUEST"; + case MFIE_TYPE_MEASURE_REPORT: + return "MEASURE_REPORT"; + case MFIE_TYPE_QUIET: + return "QUIET"; + case MFIE_TYPE_IBSS_DFS: + return "IBSS_DFS"; + case MFIE_TYPE_RSN: + return "RSN"; + case MFIE_TYPE_RATES_EX: + return "RATES_EX"; + case MFIE_TYPE_GENERIC: + return "GENERIC"; + case MFIE_TYPE_QOS_PARAMETER: + return "QOS_PARAMETER"; default: return "UNKNOWN"; } diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index b374088c5ff8..0aa9021cb95e 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -1014,7 +1014,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, goto rx_dropped; // if QoS enabled, should check the sequence for each of the AC - if( (ieee->pHTInfo->bCurRxReorderEnable == false) || !ieee->current_network.qos_data.active|| !IsDataFrame(skb->data) || IsLegacyDataFrame(skb->data)){ + if ((!ieee->pHTInfo->bCurRxReorderEnable) || !ieee->current_network.qos_data.active|| !IsDataFrame(skb->data) || IsLegacyDataFrame(skb->data)) { if (is_duplicate_packet(ieee, hdr)) goto rx_dropped; @@ -1307,7 +1307,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, } //added by amy for reorder - if(ieee->pHTInfo->bCurRxReorderEnable == false ||pTS == NULL){ + if (!ieee->pHTInfo->bCurRxReorderEnable || pTS == NULL){ //added by amy for reorder for(i = 0; i<rxb->nr_subframes; i++) { struct sk_buff *sub_skb = rxb->subframes[i]; diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c index a1f9d42833e0..39e9892c3fa6 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c @@ -1964,7 +1964,7 @@ static void ieee80211_check_auth_response(struct ieee80211_device *ieee, } if (ieee->current_network.mode == IEEE_N_24G && - bHalfSupportNmode == true) { + bHalfSupportNmode) { netdev_dbg(ieee->dev, "enter half N mode\n"); ieee->bHalfWirelessN24GMode = true; } else diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c index 5353a45ffdff..fff8d583c62f 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c @@ -336,12 +336,12 @@ static void ieee80211_tx_query_agg_cap(struct ieee80211_device *ieee, printk("===>can't get TS\n"); return; } - if (pTxTs->TxAdmittedBARecord.bValid == false) + if (!pTxTs->TxAdmittedBARecord.bValid) { TsStartAddBaProcess(ieee, pTxTs); goto FORCED_AGG_SETTING; } - else if (pTxTs->bUsingBa == false) + else if (!pTxTs->bUsingBa) { if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum, (pTxTs->TxCurSeq+1)%4096)) pTxTs->bUsingBa = true; diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c index 9ff8e056ab7f..3bde744604c2 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c @@ -364,8 +364,8 @@ int ieee80211_rx_ADDBAReq(struct ieee80211_device *ieee, struct sk_buff *skb) printk("====================>rx ADDBAREQ from :%pM\n", dst); //some other capability is not ready now. if ((ieee->current_network.qos_data.active == 0) || - (ieee->pHTInfo->bCurrentHTSupport == false)) //|| - // (ieee->pStaQos->bEnableRxImmBA == false) ) + (!ieee->pHTInfo->bCurrentHTSupport)) //|| + // (!ieee->pStaQos->bEnableRxImmBA) ) { rc = ADDBA_STATUS_REFUSED; IEEE80211_DEBUG(IEEE80211_DL_ERR, "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport); @@ -462,8 +462,8 @@ int ieee80211_rx_ADDBARsp(struct ieee80211_device *ieee, struct sk_buff *skb) // Check the capability // Since we can always receive A-MPDU, we just check if it is under HT mode. if (ieee->current_network.qos_data.active == 0 || - ieee->pHTInfo->bCurrentHTSupport == false || - ieee->pHTInfo->bCurrentAMPDUEnable == false) { + !ieee->pHTInfo->bCurrentHTSupport || + !ieee->pHTInfo->bCurrentAMPDUEnable) { IEEE80211_DEBUG(IEEE80211_DL_ERR, "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bCurrentAMPDUEnable); ReasonCode = DELBA_REASON_UNKNOWN_BA; goto OnADDBARsp_Reject; @@ -502,7 +502,7 @@ int ieee80211_rx_ADDBARsp(struct ieee80211_device *ieee, struct sk_buff *skb) IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n"); return -1; } - else if((pPendingBA->bValid == false) ||(*pDialogToken != pPendingBA->DialogToken)) + else if((!pPendingBA->bValid) ||(*pDialogToken != pPendingBA->DialogToken)) { IEEE80211_DEBUG(IEEE80211_DL_ERR, "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n"); ReasonCode = DELBA_REASON_UNKNOWN_BA; @@ -571,7 +571,6 @@ int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb) { struct rtl_80211_hdr_3addr *delba = NULL; PDELBA_PARAM_SET pDelBaParamSet = NULL; - u16 *pReasonCode = NULL; u8 *dst = NULL; if (skb->len < sizeof(struct rtl_80211_hdr_3addr) + 6) { @@ -583,7 +582,7 @@ int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb) } if (ieee->current_network.qos_data.active == 0 || - ieee->pHTInfo->bCurrentHTSupport == false ) + !ieee->pHTInfo->bCurrentHTSupport) { IEEE80211_DEBUG(IEEE80211_DL_ERR, "received DELBA while QOS or HT is not supported(%d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport); return -1; @@ -592,9 +591,7 @@ int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb) IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); delba = (struct rtl_80211_hdr_3addr *)skb->data; dst = (u8 *)(&delba->addr2[0]); - delba += sizeof(struct rtl_80211_hdr_3addr); - pDelBaParamSet = (PDELBA_PARAM_SET)(delba+2); - pReasonCode = (u16 *)(delba+4); + pDelBaParamSet = (PDELBA_PARAM_SET)&delba->payload[2]; if(pDelBaParamSet->field.Initiator == 1) { diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c index 80411c93d8fa..c27397b14adb 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c @@ -224,9 +224,9 @@ static bool IsHTHalfNmode40Bandwidth(struct ieee80211_device *ieee) bool retValue = false; PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; - if(pHTInfo->bCurrentHTSupport == false ) // wireless is n mode + if(!pHTInfo->bCurrentHTSupport) // wireless is n mode retValue = false; - else if(pHTInfo->bRegBW40MHz == false) // station supports 40 bw + else if(!pHTInfo->bRegBW40MHz) // station supports 40 bw retValue = false; else if(!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) // station in half n mode retValue = false; @@ -243,7 +243,7 @@ static bool IsHTHalfNmodeSGI(struct ieee80211_device *ieee, bool is40MHz) bool retValue = false; PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; - if(pHTInfo->bCurrentHTSupport == false ) // wireless is n mode + if(!pHTInfo->bCurrentHTSupport) // wireless is n mode retValue = false; else if(!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) // station in half n mode retValue = false; @@ -675,7 +675,7 @@ void HTConstructInfoElement(struct ieee80211_device *ieee, u8 *posHTInfo, u8 *le if ( (ieee->iw_mode == IW_MODE_ADHOC) || (ieee->iw_mode == IW_MODE_MASTER)) //ap mode is not currently supported { pHTInfoEle->ControlChl = ieee->current_network.channel; - pHTInfoEle->ExtChlOffset = ((pHT->bRegBW40MHz == false)?HT_EXTCHNL_OFFSET_NO_EXT: + pHTInfoEle->ExtChlOffset = ((!pHT->bRegBW40MHz)?HT_EXTCHNL_OFFSET_NO_EXT: (ieee->current_network.channel<=6)? HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); pHTInfoEle->RecommemdedTxWidth = pHT->bRegBW40MHz; @@ -945,7 +945,7 @@ void HTOnAssocRsp(struct ieee80211_device *ieee) static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33}; // For 11n EWC definition, 2007.07.17, by Emily static u8 EWC11NHTInfo[] = {0x00, 0x90, 0x4c, 0x34}; // For 11n EWC definition, 2007.07.17, by Emily - if (pHTInfo->bCurrentHTSupport == false) { + if (!pHTInfo->bCurrentHTSupport) { IEEE80211_DEBUG(IEEE80211_DL_ERR, "<=== HTOnAssocRsp(): HT_DISABLE\n"); return; } @@ -976,7 +976,7 @@ void HTOnAssocRsp(struct ieee80211_device *ieee) // HTSetConnectBwMode(ieee, (HT_CHANNEL_WIDTH)(pPeerHTCap->ChlWidth), (HT_EXTCHNL_OFFSET)(pPeerHTInfo->ExtChlOffset)); -// if(pHTInfo->bCurBW40MHz == true) +// if (pHTInfo->bCurBW40MHz) pHTInfo->bCurTxBW40MHz = ((pPeerHTInfo->RecommemdedTxWidth == 1)?true:false); // @@ -1341,7 +1341,7 @@ void HTSetConnectBwMode(struct ieee80211_device *ieee, HT_CHANNEL_WIDTH Bandwidt PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; // u32 flags = 0; - if(pHTInfo->bRegBW40MHz == false) + if(!pHTInfo->bRegBW40MHz) return; diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c index b89105dbcbba..f33c74342cf3 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c @@ -584,7 +584,7 @@ void RemoveAllTS(struct ieee80211_device *ieee) void TsStartAddBaProcess(struct ieee80211_device *ieee, PTX_TS_RECORD pTxTS) { - if(pTxTS->bAddBaReqInProgress == false) + if(!pTxTS->bAddBaReqInProgress) { pTxTS->bAddBaReqInProgress = true; if(pTxTS->bAddBaReqDelayed) diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index b852396d21e6..6f6fe38081bc 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -2043,16 +2043,9 @@ static bool GetNmodeSupportBySecCfg8192(struct net_device *dev) static bool GetHalfNmodeSupportByAPs819xUsb(struct net_device *dev) { - bool Reval; struct r8192_priv *priv = ieee80211_priv(dev); - struct ieee80211_device *ieee = priv->ieee80211; - - if (ieee->bHalfWirelessN24GMode == true) - Reval = true; - else - Reval = false; - return Reval; + return priv->ieee80211->bHalfWirelessN24GMode; } static void rtl8192_refresh_supportrate(struct r8192_priv *priv) @@ -2762,7 +2755,7 @@ static bool rtl8192_adapter_start(struct net_device *dev) // #ifdef TO_DO_LIST if (Adapter->ResetProgress == RESET_TYPE_NORESET) { - if (pMgntInfo->RegRfOff == true) { /* User disable RF via registry. */ + if (pMgntInfo->RegRfOff) { /* User disable RF via registry. */ RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RegRfOff ----------\n")); MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_SW); // Those actions will be discard in MgntActSet_RF_State because of the same state @@ -4406,7 +4399,8 @@ static void query_rxdesc_status(struct sk_buff *skb, /* RTL8190 set this bit to indicate that Hw does not decrypt packet */ stats->Decrypted = !desc->SWDec; - if ((priv->ieee80211->pHTInfo->bCurrentHTSupport == true) && (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP)) + if ((priv->ieee80211->pHTInfo->bCurrentHTSupport) && + (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP)) stats->bHwError = false; else stats->bHwError = stats->bCRC|stats->bICV; diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c index 7ca5d8fbc57f..5277f2eec033 100644 --- a/drivers/staging/rtl8192u/r8192U_dm.c +++ b/drivers/staging/rtl8192u/r8192U_dm.c @@ -438,7 +438,7 @@ static void dm_bandwidth_autoswitch(struct net_device *dev) if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 || !priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable) return; - if (priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz == false) { /* If send packets in 40 Mhz in 20/40 */ + if (!priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz) { /* If send packets in 40 Mhz in 20/40 */ if (priv->undecorated_smoothed_pwdb <= priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz) priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = true; } else { /* in force send packets in 20 Mhz in 20/40 */ @@ -1731,7 +1731,7 @@ static void dm_dig_init(struct net_device *dev) *---------------------------------------------------------------------------*/ static void dm_ctrl_initgain_byrssi(struct net_device *dev) { - if (dm_digtable.dig_enable_flag == false) + if (!dm_digtable.dig_enable_flag) return; if (dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM) @@ -1750,7 +1750,7 @@ static void dm_ctrl_initgain_byrssi_by_driverrssi( u8 i; static u8 fw_dig; - if (dm_digtable.dig_enable_flag == false) + if (!dm_digtable.dig_enable_flag) return; /*DbgPrint("Dig by Sw Rssi\n");*/ @@ -1792,7 +1792,7 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( static u32 reset_cnt; u8 i; - if (dm_digtable.dig_enable_flag == false) + if (!dm_digtable.dig_enable_flag) return; if (dm_digtable.dig_algorithm_switch) { diff --git a/drivers/staging/rtl8192u/r819xU_firmware.c b/drivers/staging/rtl8192u/r819xU_firmware.c index 742725e9bfc1..08302dfb0d90 100644 --- a/drivers/staging/rtl8192u/r819xU_firmware.c +++ b/drivers/staging/rtl8192u/r819xU_firmware.c @@ -91,7 +91,7 @@ static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address, if (!priv->ieee80211->check_nic_enough_desc(dev, index) || (!skb_queue_empty(&priv->ieee80211->skb_waitQ[index])) || (priv->ieee80211->queue_stop)) { - RT_TRACE(COMP_FIRMWARE,"=====================================================> tx full!\n"); + RT_TRACE(COMP_FIRMWARE, "=====================================================> tx full!\n"); skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb); } else { priv->ieee80211->softmac_hard_start_xmit(skb, dev); @@ -144,7 +144,8 @@ static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev) /* Turn On CPU */ read_nic_dword(dev, CPU_GEN, &CPU_status); - write_nic_byte(dev, CPU_GEN, (u8)((CPU_status|CPU_GEN_PWR_STB_CPU)&0xff)); + write_nic_byte(dev, CPU_GEN, + (u8)((CPU_status | CPU_GEN_PWR_STB_CPU) & 0xff)); mdelay(1000); /* Check whether CPU boot OK */ @@ -242,7 +243,7 @@ bool init_firmware(struct net_device *dev) * or read image file from array. Default load from IMG file */ if (rst_opt == OPT_SYSTEM_RESET) { - rc = request_firmware(&fw_entry, fw_name[init_step],&priv->udev->dev); + rc = request_firmware(&fw_entry, fw_name[init_step], &priv->udev->dev); if (rc < 0) { RT_TRACE(COMP_ERR, "request firmware fail!\n"); goto download_firmware_fail; @@ -254,12 +255,12 @@ bool init_firmware(struct net_device *dev) } if (init_step != FW_INIT_STEP1_MAIN) { - memcpy(pfirmware->firmware_buf,fw_entry->data,fw_entry->size); + memcpy(pfirmware->firmware_buf, fw_entry->data, fw_entry->size); mapped_file = pfirmware->firmware_buf; file_length = fw_entry->size; } else { memset(pfirmware->firmware_buf, 0, 128); - memcpy(&pfirmware->firmware_buf[128],fw_entry->data,fw_entry->size); + memcpy(&pfirmware->firmware_buf[128], fw_entry->data, fw_entry->size); mapped_file = pfirmware->firmware_buf; file_length = fw_entry->size + 128; } @@ -319,7 +320,7 @@ bool init_firmware(struct net_device *dev) rt_status = CPUcheck_firmware_ready(dev); if (!rt_status) { - RT_TRACE(COMP_ERR, "CPUcheck_firmware_ready fail(%d)!\n",rt_status); + RT_TRACE(COMP_ERR, "CPUcheck_firmware_ready fail(%d)!\n", rt_status); goto download_firmware_fail; } diff --git a/drivers/staging/rtl8712/ieee80211.c b/drivers/staging/rtl8712/ieee80211.c index 57868085ce58..c5527c1ccaa6 100644 --- a/drivers/staging/rtl8712/ieee80211.c +++ b/drivers/staging/rtl8712/ieee80211.c @@ -134,22 +134,20 @@ u8 *r8712_get_ie(u8 *pbuf, sint index, sint *len, sint limit) return NULL; } -static void set_supported_rate(u8 *SupportedRates, uint mode) +static void set_supported_rate(u8 *rates, uint mode) { - memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX); + memset(rates, 0, NDIS_802_11_LENGTH_RATES_EX); switch (mode) { case WIRELESS_11B: - memcpy(SupportedRates, WIFI_CCKRATES, - IEEE80211_CCK_RATE_LEN); + memcpy(rates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN); break; case WIRELESS_11G: case WIRELESS_11A: - memcpy(SupportedRates, WIFI_OFDMRATES, - IEEE80211_NUM_OFDM_RATESLEN); + memcpy(rates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN); break; case WIRELESS_11BG: - memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN); - memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, + memcpy(rates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN); + memcpy(rates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN); break; } @@ -195,17 +193,16 @@ int r8712_generate_ie(struct registry_priv *pregistrypriv) ie = r8712_set_ie(ie, _SSID_IE_, pdev_network->Ssid.SsidLength, pdev_network->Ssid.Ssid, &sz); /*supported rates*/ - set_supported_rate(pdev_network->SupportedRates, - pregistrypriv->wireless_mode); - rateLen = r8712_get_rateset_len(pdev_network->SupportedRates); + set_supported_rate(pdev_network->rates, pregistrypriv->wireless_mode); + rateLen = r8712_get_rateset_len(pdev_network->rates); if (rateLen > 8) { ie = r8712_set_ie(ie, _SUPPORTEDRATES_IE_, 8, - pdev_network->SupportedRates, &sz); + pdev_network->rates, &sz); ie = r8712_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), - (pdev_network->SupportedRates + 8), &sz); + (pdev_network->rates + 8), &sz); } else ie = r8712_set_ie(ie, _SUPPORTEDRATES_IE_, - rateLen, pdev_network->SupportedRates, &sz); + rateLen, pdev_network->rates, &sz); /*DS parameter set*/ ie = r8712_set_ie(ie, _DSSET_IE_, 1, (u8 *)&(pdev_network->Configuration.DSConfig), &sz); diff --git a/drivers/staging/rtl8712/rtl871x_cmd.c b/drivers/staging/rtl8712/rtl871x_cmd.c index e35854d28f90..ef7182961002 100644 --- a/drivers/staging/rtl8712/rtl871x_cmd.c +++ b/drivers/staging/rtl8712/rtl871x_cmd.c @@ -456,9 +456,7 @@ u8 r8712_createbss_cmd(struct _adapter *padapter) INIT_LIST_HEAD(&pcmd->list); pcmd->cmdcode = _CreateBss_CMD_; pcmd->parmbuf = (unsigned char *)pdev_network; - pcmd->cmdsz = r8712_get_ndis_wlan_bssid_ex_sz(( - struct ndis_wlan_bssid_ex *) - pdev_network); + pcmd->cmdsz = r8712_get_wlan_bssid_ex_sz(pdev_network); pcmd->rsp = NULL; pcmd->rspsz = 0; /* notes: translate IELength & Length after assign to cmdsz; */ @@ -471,8 +469,7 @@ u8 r8712_createbss_cmd(struct _adapter *padapter) u8 r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork) { - uint t_len = 0; - struct ndis_wlan_bssid_ex *psecnetwork; + struct wlan_bssid_ex *psecnetwork; struct cmd_obj *pcmd; struct cmd_priv *pcmdpriv = &padapter->cmdpriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; @@ -486,14 +483,6 @@ u8 r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork) pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC); if (pcmd == NULL) return _FAIL; - t_len = sizeof(u32) + 6 * sizeof(unsigned char) + 2 + - sizeof(struct ndis_802_11_ssid) + sizeof(u32) + - sizeof(s32) + - sizeof(enum NDIS_802_11_NETWORK_TYPE) + - sizeof(struct NDIS_802_11_CONFIGURATION) + - sizeof(enum NDIS_802_11_NETWORK_INFRASTRUCTURE) + - sizeof(NDIS_802_11_RATES_EX) + - sizeof(u32) + MAX_IE_SZ; /* for hidden ap to set fw_state here */ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) != @@ -511,12 +500,12 @@ u8 r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork) break; } } - psecnetwork = (struct ndis_wlan_bssid_ex *)&psecuritypriv->sec_bss; + psecnetwork = &psecuritypriv->sec_bss; if (psecnetwork == NULL) { kfree(pcmd); return _FAIL; } - memcpy(psecnetwork, &pnetwork->network, t_len); + memcpy(psecnetwork, &pnetwork->network, sizeof(*psecnetwork)); psecuritypriv->authenticator_ie[0] = (unsigned char) psecnetwork->IELength; if ((psecnetwork->IELength-12) < (256 - 1)) @@ -575,7 +564,7 @@ u8 r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork) memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0], 255); /* get cmdsz before endian conversion */ - pcmd->cmdsz = r8712_get_ndis_wlan_bssid_ex_sz(psecnetwork); + pcmd->cmdsz = r8712_get_wlan_bssid_ex_sz(psecnetwork); #ifdef __BIG_ENDIAN /* wlan_network endian conversion */ psecnetwork->Length = cpu_to_le32(psecnetwork->Length); @@ -903,8 +892,7 @@ void r8712_createbss_cmd_callback(struct _adapter *padapter, struct sta_info *psta = NULL; struct wlan_network *pwlan = NULL; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ndis_wlan_bssid_ex *pnetwork = (struct ndis_wlan_bssid_ex *) - pcmd->parmbuf; + struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf; struct wlan_network *tgt_network = &(pmlmepriv->cur_network); if (pcmd->res != H2C_SUCCESS) @@ -958,11 +946,11 @@ void r8712_createbss_cmd_callback(struct _adapter *padapter, } else list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue); - pnetwork->Length = r8712_get_ndis_wlan_bssid_ex_sz(pnetwork); + pnetwork->Length = r8712_get_wlan_bssid_ex_sz(pnetwork); memcpy(&(pwlan->network), pnetwork, pnetwork->Length); pwlan->fixed = true; memcpy(&tgt_network->network, pnetwork, - (r8712_get_ndis_wlan_bssid_ex_sz(pnetwork))); + (r8712_get_wlan_bssid_ex_sz(pnetwork))); if (pmlmepriv->fw_state & _FW_UNDER_LINKING) pmlmepriv->fw_state ^= _FW_UNDER_LINKING; /* we will set _FW_LINKED when there is one more sat to diff --git a/drivers/staging/rtl8712/rtl871x_cmd.h b/drivers/staging/rtl8712/rtl871x_cmd.h index cb8225b94cf1..818cd8807a38 100644 --- a/drivers/staging/rtl8712/rtl871x_cmd.h +++ b/drivers/staging/rtl8712/rtl871x_cmd.h @@ -123,15 +123,6 @@ struct usb_suspend_parm { }; /* - * Caller Mode: Infra, Ad-Hoc - * Notes: To join the specified bss - * Command Event Mode - */ -struct joinbss_parm { - struct ndis_wlan_bssid_ex network; -}; - -/* * Caller Mode: Infra, Ad-HoC(C) * Notes: To disconnect the current associated BSS * Command Mode @@ -141,15 +132,6 @@ struct disconnect_parm { }; /* - * Caller Mode: AP, Ad-HoC(M) - * Notes: To create a BSS - * Command Mode - */ -struct createbss_parm { - struct ndis_wlan_bssid_ex network; -}; - -/* * Caller Mode: AP, Ad-HoC, Infra * Notes: To set the NIC mode of RTL8711 * Command Mode diff --git a/drivers/staging/rtl8712/rtl871x_event.h b/drivers/staging/rtl8712/rtl871x_event.h index e03ee90d2870..697c8d735150 100644 --- a/drivers/staging/rtl8712/rtl871x_event.h +++ b/drivers/staging/rtl8712/rtl871x_event.h @@ -36,7 +36,7 @@ * Used to report a bss has been scanned */ struct survey_event { - struct ndis_wlan_bssid_ex bss; + struct wlan_bssid_ex bss; }; /* diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c index 3388f971fb48..143be0fdc578 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c @@ -203,14 +203,12 @@ static inline char *translate_scan(struct _adapter *padapter, } /* Add the protocol name */ iwe.cmd = SIOCGIWNAME; - if ((r8712_is_cckratesonly_included((u8 *)&pnetwork->network. - SupportedRates)) == true) { + if (r8712_is_cckratesonly_included(pnetwork->network.rates)) { if (ht_cap == true) snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn"); else snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b"); - } else if ((r8712_is_cckrates_included((u8 *)&pnetwork->network. - SupportedRates)) == true) { + } else if (r8712_is_cckrates_included(pnetwork->network.rates)) { if (ht_cap == true) snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn"); else @@ -270,9 +268,9 @@ static inline char *translate_scan(struct _adapter *padapter, iwe.u.bitrate.disabled = 0; iwe.u.bitrate.value = 0; i = 0; - while (pnetwork->network.SupportedRates[i] != 0) { + while (pnetwork->network.rates[i] != 0) { /* Bit rate given in 500 kb/s units */ - iwe.u.bitrate.value = (pnetwork->network.SupportedRates[i++] & + iwe.u.bitrate.value = (pnetwork->network.rates[i++] & 0x7F) * 500000; current_val = iwe_stream_add_value(info, start, current_val, stop, &iwe, IW_EV_PARAM_LEN); @@ -634,8 +632,8 @@ static int r8711_wx_get_name(struct net_device *dev, char *p; u8 ht_cap = false; struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; - NDIS_802_11_RATES_EX *prates = NULL; + struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; + u8 *prates; if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) { @@ -644,15 +642,15 @@ static int r8711_wx_get_name(struct net_device *dev, &ht_ielen, pcur_bss->IELength - 12); if (p && ht_ielen > 0) ht_cap = true; - prates = &pcur_bss->SupportedRates; - if (r8712_is_cckratesonly_included((u8 *)prates) == true) { + prates = pcur_bss->rates; + if (r8712_is_cckratesonly_included(prates) == true) { if (ht_cap == true) snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn"); else snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b"); - } else if ((r8712_is_cckrates_included((u8 *)prates)) == true) { + } else if ((r8712_is_cckrates_included(prates)) == true) { if (ht_cap == true) snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn"); @@ -723,7 +721,7 @@ static int r8711_wx_get_freq(struct net_device *dev, { struct _adapter *padapter = netdev_priv(dev); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; + struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { wrqu->freq.m = ieee80211_wlan_frequencies[ @@ -1111,7 +1109,7 @@ static int r8711_wx_get_wap(struct net_device *dev, { struct _adapter *padapter = netdev_priv(dev); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; + struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; wrqu->ap_addr.sa_family = ARPHRD_ETHER; if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE | @@ -1327,7 +1325,7 @@ static int r8711_wx_get_essid(struct net_device *dev, { struct _adapter *padapter = netdev_priv(dev); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; + struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; u32 len, ret = 0; if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) { @@ -1419,7 +1417,7 @@ static int r8711_wx_get_rate(struct net_device *dev, { struct _adapter *padapter = netdev_priv(dev); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; + struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; struct ieee80211_ht_cap *pht_capie; unsigned char rf_type = padapter->registrypriv.rf_config; int i; @@ -1444,9 +1442,9 @@ static int r8711_wx_get_rate(struct net_device *dev, (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40)) ? 1 : 0; } - while ((pcur_bss->SupportedRates[i] != 0) && - (pcur_bss->SupportedRates[i] != 0xFF)) { - rate = pcur_bss->SupportedRates[i] & 0x7F; + while ((pcur_bss->rates[i] != 0) && + (pcur_bss->rates[i] != 0xFF)) { + rate = pcur_bss->rates[i] & 0x7F; if (rate > max_rate) max_rate = rate; wrqu->bitrate.fixed = 0; /* no auto select */ diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c index c044b0e55ba9..fc5dbea08cb4 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.c +++ b/drivers/staging/rtl8712/rtl871x_mlme.c @@ -208,19 +208,9 @@ void r8712_generate_random_ibss(u8 *pibss) pibss[5] = (u8)((curtime>>16) & 0xff); } -uint r8712_get_ndis_wlan_bssid_ex_sz(struct ndis_wlan_bssid_ex *bss) +uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss) { - uint t_len; - - t_len = sizeof(u32) + 6 * sizeof(unsigned long) + 2 + - sizeof(struct ndis_802_11_ssid) + sizeof(u32) + - sizeof(s32) + - sizeof(enum NDIS_802_11_NETWORK_TYPE) + - sizeof(struct NDIS_802_11_CONFIGURATION) + - sizeof(enum NDIS_802_11_NETWORK_INFRASTRUCTURE) + - sizeof(NDIS_802_11_RATES_EX) + - sizeof(u32) + bss->IELength; - return t_len; + return sizeof(*bss) + bss->IELength - MAX_IE_SZ; } u8 *r8712_get_capability_from_ie(u8 *ie) @@ -286,8 +276,8 @@ int r8712_is_same_ibss(struct _adapter *adapter, struct wlan_network *pnetwork) } -static int is_same_network(struct ndis_wlan_bssid_ex *src, - struct ndis_wlan_bssid_ex *dst) +static int is_same_network(struct wlan_bssid_ex *src, + struct wlan_bssid_ex *dst) { u16 s_cap, d_cap; @@ -332,8 +322,8 @@ struct wlan_network *r8712_get_oldest_wlan_network( return oldest; } -static void update_network(struct ndis_wlan_bssid_ex *dst, - struct ndis_wlan_bssid_ex *src, +static void update_network(struct wlan_bssid_ex *dst, + struct wlan_bssid_ex *src, struct _adapter *padapter) { u32 last_evm = 0, tmpVal; @@ -366,11 +356,11 @@ static void update_network(struct ndis_wlan_bssid_ex *dst, src->Rssi = padapter->recvpriv.signal; } else src->Rssi = (src->Rssi + dst->Rssi) / 2; - memcpy((u8 *)dst, (u8 *)src, r8712_get_ndis_wlan_bssid_ex_sz(src)); + memcpy((u8 *)dst, (u8 *)src, r8712_get_wlan_bssid_ex_sz(src)); } static void update_current_network(struct _adapter *adapter, - struct ndis_wlan_bssid_ex *pnetwork) + struct wlan_bssid_ex *pnetwork) { struct mlme_priv *pmlmepriv = &adapter->mlmepriv; @@ -388,7 +378,7 @@ static void update_current_network(struct _adapter *adapter, Caller must hold pmlmepriv->lock first. */ static void update_scanned_network(struct _adapter *adapter, - struct ndis_wlan_bssid_ex *target) + struct wlan_bssid_ex *target) { struct list_head *plist, *phead; @@ -426,7 +416,7 @@ static void update_scanned_network(struct _adapter *adapter, target->Rssi = (pnetwork->network.Rssi + target->Rssi) / 2; memcpy(&pnetwork->network, target, - r8712_get_ndis_wlan_bssid_ex_sz(target)); + r8712_get_wlan_bssid_ex_sz(target)); pnetwork->last_scanned = jiffies; } else { /* Otherwise just pull from the free list */ @@ -434,7 +424,7 @@ static void update_scanned_network(struct _adapter *adapter, pnetwork = alloc_network(pmlmepriv); if (pnetwork == NULL) return; - bssid_ex_sz = r8712_get_ndis_wlan_bssid_ex_sz(target); + bssid_ex_sz = r8712_get_wlan_bssid_ex_sz(target); target->Length = bssid_ex_sz; memcpy(&pnetwork->network, target, bssid_ex_sz); list_add_tail(&pnetwork->list, &queue->queue); @@ -451,7 +441,7 @@ static void update_scanned_network(struct _adapter *adapter, } static void rtl8711_add_network(struct _adapter *adapter, - struct ndis_wlan_bssid_ex *pnetwork) + struct wlan_bssid_ex *pnetwork) { unsigned long irqL; struct mlme_priv *pmlmepriv = &(((struct _adapter *)adapter)->mlmepriv); @@ -507,10 +497,10 @@ void r8712_survey_event_callback(struct _adapter *adapter, u8 *pbuf) { unsigned long flags; u32 len; - struct ndis_wlan_bssid_ex *pnetwork; + struct wlan_bssid_ex *pnetwork; struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - pnetwork = (struct ndis_wlan_bssid_ex *)pbuf; + pnetwork = (struct wlan_bssid_ex *)pbuf; #ifdef __BIG_ENDIAN /* endian_convert */ pnetwork->Length = le32_to_cpu(pnetwork->Length); @@ -538,7 +528,7 @@ void r8712_survey_event_callback(struct _adapter *adapter, u8 *pbuf) le32_to_cpu(pnetwork->InfrastructureMode); pnetwork->IELength = le32_to_cpu(pnetwork->IELength); #endif - len = r8712_get_ndis_wlan_bssid_ex_sz(pnetwork); + len = r8712_get_wlan_bssid_ex_sz(pnetwork); if (len > sizeof(struct wlan_bssid_ex)) return; spin_lock_irqsave(&pmlmepriv->lock2, flags); @@ -769,7 +759,7 @@ void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf) the_same_macaddr = !memcmp(pnetwork->network.MacAddress, cur_network->network.MacAddress, ETH_ALEN); pnetwork->network.Length = - r8712_get_ndis_wlan_bssid_ex_sz(&pnetwork->network); + r8712_get_wlan_bssid_ex_sz(&pnetwork->network); spin_lock_irqsave(&pmlmepriv->lock, irqL); if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex)) goto ignore_joinbss_callback; @@ -1001,7 +991,7 @@ void r8712_stadel_event_callback(struct _adapter *adapter, u8 *pbuf) pdev_network = &(adapter->registrypriv.dev_network); pibss = adapter->registrypriv.dev_network.MacAddress; memcpy(pdev_network, &tgt_network->network, - r8712_get_ndis_wlan_bssid_ex_sz(&tgt_network-> + r8712_get_wlan_bssid_ex_sz(&tgt_network-> network)); memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, @@ -1668,8 +1658,7 @@ void r8712_update_registrypriv_dev_network(struct _adapter *adapter) */ sz = r8712_generate_ie(pregistrypriv); pdev_network->IELength = sz; - pdev_network->Length = r8712_get_ndis_wlan_bssid_ex_sz( - (struct ndis_wlan_bssid_ex *)pdev_network); + pdev_network->Length = r8712_get_wlan_bssid_ex_sz(pdev_network); } /*the function is at passive_level*/ diff --git a/drivers/staging/rtl8712/rtl871x_mlme.h b/drivers/staging/rtl8712/rtl871x_mlme.h index 42bd0bf8a816..08d6c986c11e 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.h +++ b/drivers/staging/rtl8712/rtl871x_mlme.h @@ -202,7 +202,7 @@ sint r8712_set_key(struct _adapter *adapter, struct security_priv *psecuritypriv, sint keyid); sint r8712_set_auth(struct _adapter *adapter, struct security_priv *psecuritypriv); -uint r8712_get_ndis_wlan_bssid_ex_sz(struct ndis_wlan_bssid_ex *bss); +uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss); void r8712_generate_random_ibss(u8 *pibss); u8 *r8712_get_capability_from_ie(u8 *ie); struct wlan_network *r8712_get_oldest_wlan_network( diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c b/drivers/staging/rtl8712/rtl871x_mp_ioctl.c index 0b5461208eb9..77f01bf1ca3c 100644 --- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c +++ b/drivers/staging/rtl8712/rtl871x_mp_ioctl.c @@ -160,13 +160,13 @@ static int mp_start_test(struct _adapter *padapter) struct mp_priv *pmppriv = &padapter->mppriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct wlan_network *tgt_network = &pmlmepriv->cur_network; - struct ndis_wlan_bssid_ex bssid; + struct wlan_bssid_ex bssid; struct sta_info *psta; unsigned long length; unsigned long irqL; int res = _SUCCESS; - /* 3 1. initialize a new struct ndis_wlan_bssid_ex */ + /* 3 1. initialize a new struct wlan_bssid_ex */ memcpy(bssid.MacAddress, pmppriv->network_macaddr, ETH_ALEN); bssid.Ssid.SsidLength = 16; memcpy(bssid.Ssid.Ssid, (unsigned char *)"mp_pseudo_adhoc", @@ -174,7 +174,7 @@ static int mp_start_test(struct _adapter *padapter) bssid.InfrastructureMode = Ndis802_11IBSS; bssid.NetworkTypeInUse = Ndis802_11DS; bssid.IELength = 0; - length = r8712_get_ndis_wlan_bssid_ex_sz(&bssid); + length = r8712_get_wlan_bssid_ex_sz(&bssid); if (length % 4) { /*round up to multiple of 4 bytes.*/ bssid.Length = ((length >> 2) + 1) << 2; diff --git a/drivers/staging/rtl8712/wlan_bssdef.h b/drivers/staging/rtl8712/wlan_bssdef.h index 2ea8a3d6b705..fda5707c4acd 100644 --- a/drivers/staging/rtl8712/wlan_bssdef.h +++ b/drivers/staging/rtl8712/wlan_bssdef.h @@ -32,11 +32,6 @@ #define NDIS_802_11_LENGTH_RATES 8 #define NDIS_802_11_LENGTH_RATES_EX 16 -/* Set of 8 data rates*/ -typedef unsigned char NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES]; -/* Set of 16 data rates */ -typedef unsigned char NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX]; - struct ndis_802_11_ssid { u32 SsidLength; u8 Ssid[32]; @@ -83,18 +78,7 @@ struct NDIS_802_11_FIXED_IEs { u16 Capabilities; }; -/* - * Length is the 4 bytes multiples of the sume of - * 6 * sizeof (unsigned char) + 2 + sizeof (ndis_802_11_ssid) + sizeof (u32) - * + sizeof (s32) + sizeof (NDIS_802_11_NETWORK_TYPE) - * + sizeof (struct NDIS_802_11_CONFIGURATION) - * + sizeof (NDIS_802_11_RATES_EX) + IELength - - * Except the IELength, all other fields are fixed length. Therefore, we can - * define a macro to present the partial sum. - */ - -struct ndis_wlan_bssid_ex { +struct wlan_bssid_ex { u32 Length; unsigned char MacAddress[6]; u8 Reserved[2]; @@ -104,7 +88,8 @@ struct ndis_wlan_bssid_ex { enum NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; struct NDIS_802_11_CONFIGURATION Configuration; enum NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; - NDIS_802_11_RATES_EX SupportedRates; + u8 rates[NDIS_802_11_LENGTH_RATES_EX]; + /* number of content bytes in EIs, which varies */ u32 IELength; /*(timestamp, beacon interval, and capability information) */ u8 IEs[MAX_IE_SZ]; @@ -213,7 +198,7 @@ struct wlan_network { unsigned int last_scanned; /*timestamp for the network */ int aid; /*will only be valid when a BSS is joined. */ int join_res; - struct ndis_wlan_bssid_ex network; /*must be the last item */ + struct wlan_bssid_ex network; /*must be the last item */ }; enum VRTL_CARRIER_SENSE { @@ -244,24 +229,5 @@ enum UAPSD_MAX_SP { #define NUM_PRE_AUTH_KEY 16 #define NUM_PMKID_CACHE NUM_PRE_AUTH_KEY -/* - * WPA2 - */ -struct wlan_bssid_ex { - u32 Length; - unsigned char MacAddress[6]; - u8 Reserved[2]; - struct ndis_802_11_ssid Ssid; - u32 Privacy; - s32 Rssi; - enum NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; - struct NDIS_802_11_CONFIGURATION Configuration; - enum NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; - NDIS_802_11_RATES_EX SupportedRates; - u32 IELength; - u8 IEs[MAX_IE_SZ]; /* (timestamp, beacon interval, and capability - * information) */ -}; - #endif /* #ifndef WLAN_BSSDEF_H_ */ diff --git a/drivers/staging/rtl8723au/core/rtw_recv.c b/drivers/staging/rtl8723au/core/rtw_recv.c index 274a4b65c022..ad0549c66529 100644 --- a/drivers/staging/rtl8723au/core/rtw_recv.c +++ b/drivers/staging/rtl8723au/core/rtw_recv.c @@ -1554,8 +1554,7 @@ static int wlanhdr_to_ethhdr (struct recv_frame *precvframe) ether_addr_copy(ptr + ETH_ALEN, pattrib->src); if (!bsnaphdr) { - len = htons(len); - memcpy(ptr + 12, &len, 2); + put_unaligned_be16(len, ptr + 12); } diff --git a/drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c b/drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c index 342dec3e939f..a63c6cb88bc9 100644 --- a/drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c +++ b/drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c @@ -21,7 +21,7 @@ odm_ConfigRFReg_8723A( struct dm_odm_t *pDM_Odm, u32 Addr, u32 Data, - enum RF_RADIO_PATH RF_PATH, + enum RF_RADIO_PATH RF_PATH, u32 RegAddr ) { diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c b/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c index cb5076abda8b..cf2388f4f6e7 100644 --- a/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c +++ b/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c @@ -1838,7 +1838,7 @@ Hal_EfuseParseThermalMeter_8723A(struct rtw_adapter *padapter, static void rtl8723a_cal_txdesc_chksum(struct tx_desc *ptxdesc) { - u16 *usPtr = (u16 *) ptxdesc; + __le16 *usPtr = (__le16 *)ptxdesc; u32 count = 16; /* (32 bytes / 2 bytes per XOR) => 16 times */ u32 index; u16 checksum = 0; @@ -1847,7 +1847,7 @@ static void rtl8723a_cal_txdesc_chksum(struct tx_desc *ptxdesc) ptxdesc->txdw7 &= cpu_to_le32(0xffff0000); for (index = 0; index < count; index++) - checksum ^= le16_to_cpu(*(usPtr + index)); + checksum ^= le16_to_cpu(usPtr[index]); ptxdesc->txdw7 |= cpu_to_le32(checksum & 0x0000ffff); } diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index ee818b0dc401..cdaa1aba50ed 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -1121,11 +1121,10 @@ static int ms_read_attribute_info(struct rtsx_chip *chip) #ifdef SUPPORT_MSXC if ((buf[cur_addr_off + 8] == 0x10) || - (buf[cur_addr_off + 8] == 0x13)) + (buf[cur_addr_off + 8] == 0x13)) { #else - if (buf[cur_addr_off + 8] == 0x10) + if (buf[cur_addr_off + 8] == 0x10) { #endif - { sys_info_addr = ((u32)buf[cur_addr_off + 0] << 24) | ((u32)buf[cur_addr_off + 1] << 16) | ((u32)buf[cur_addr_off + 2] << 8) | diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c index cb4157960fad..d6c498209b2c 100644 --- a/drivers/staging/rts5208/sd.c +++ b/drivers/staging/rts5208/sd.c @@ -246,11 +246,10 @@ RTY_SEND_CMD: } } #ifdef SUPPORT_SD_LOCK - if (ptr[1] & 0x7D) + if (ptr[1] & 0x7D) { #else - if (ptr[1] & 0x7F) + if (ptr[1] & 0x7F) { #endif - { dev_dbg(rtsx_dev(chip), "ptr[1]: 0x%02x\n", ptr[1]); rtsx_trace(chip); @@ -4148,11 +4147,10 @@ RTY_SEND_CMD: } } #ifdef SUPPORT_SD_LOCK - if (ptr[1] & 0x7D) + if (ptr[1] & 0x7D) { #else - if (ptr[1] & 0x7F) + if (ptr[1] & 0x7F) { #endif - { rtsx_trace(chip); return STATUS_FAIL; } diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index a609f3e67256..858597087ba7 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -2329,6 +2329,7 @@ static int slic_if_init(struct adapter *adapter, unsigned long *flags) if (!adapter->isp_initialized) { unsigned long flags; + pshmem = (struct slic_shmem *)(unsigned long) adapter->phys_shmem; diff --git a/drivers/staging/sm750fb/ddk750_power.c b/drivers/staging/sm750fb/ddk750_power.c index c8c51be53d68..e580dab2b625 100644 --- a/drivers/staging/sm750fb/ddk750_power.c +++ b/drivers/staging/sm750fb/ddk750_power.c @@ -8,7 +8,8 @@ void ddk750_setDPMS(DPMS_t state) if (getChipType() == SM750LE) { value = PEEK32(CRT_DISPLAY_CTRL); - POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(value, CRT_DISPLAY_CTRL, DPMS, state)); + POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(value, CRT_DISPLAY_CTRL, + DPMS, state)); } else { value = PEEK32(SYSTEM_CTRL); value = FIELD_VALUE(value, SYSTEM_CTRL, DPMS, state); @@ -20,7 +21,7 @@ unsigned int getPowerMode(void) { if (getChipType() == SM750LE) return 0; - return (FIELD_GET(PEEK32(POWER_MODE_CTRL), POWER_MODE_CTRL, MODE)); + return FIELD_GET(PEEK32(POWER_MODE_CTRL), POWER_MODE_CTRL, MODE); } @@ -39,15 +40,18 @@ void setPowerMode(unsigned int powerMode) switch (powerMode) { case POWER_MODE_CTRL_MODE_MODE0: - control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, MODE0); + control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, + MODE0); break; case POWER_MODE_CTRL_MODE_MODE1: - control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, MODE1); + control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, + MODE1); break; case POWER_MODE_CTRL_MODE_SLEEP: - control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, SLEEP); + control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, + SLEEP); break; default: @@ -138,8 +142,9 @@ void enableZVPort(unsigned int enable) gate = FIELD_SET(gate, CURRENT_GATE, I2C, ON); #endif } else { - /* Disable ZV Port Gate. There is no way to know whether the GPIO pins are being used - or not. Therefore, do not disable the GPIO gate. */ + /* Disable ZV Port Gate. There is no way to know whether the + GPIO pins are being used or not. Therefore, do not disable the + GPIO gate. */ gate = FIELD_SET(gate, CURRENT_GATE, ZVPORT, OFF); } diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index c7ab8189671f..07f8afd2defe 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -26,7 +26,6 @@ int smi_indent; - /* * #ifdef __BIG_ENDIAN * ssize_t lynxfb_ops_write(struct fb_info *info, const char __user *buf, @@ -40,7 +39,6 @@ typedef void (*PROC_SPEC_SETUP)(struct lynx_share*, char *); typedef int (*PROC_SPEC_MAP)(struct lynx_share*, struct pci_dev*); typedef int (*PROC_SPEC_INITHW)(struct lynx_share*, struct pci_dev*); - /* common var for all device */ static int g_hwcursor = 1; static int g_noaccel; @@ -51,7 +49,6 @@ static char *g_settings; static int g_dualview; static char *g_option; - static const struct fb_videomode lynx750_ext[] = { /* 1024x600-60 VESA [1.71:1] */ {NULL, 60, 1024, 600, 20423, 144, 40, 18, 1, 104, 3, @@ -115,8 +112,6 @@ static const struct fb_videomode lynx750_ext[] = { }; - - /* no hardware cursor supported under version 2.6.10, kernel bug */ static int lynxfb_ops_cursor(struct fb_info *info, struct fb_cursor *fbcursor) { @@ -149,18 +144,17 @@ static int lynxfb_ops_cursor(struct fb_info *info, struct fb_cursor *fbcursor) /* get the 16bit color of kernel means */ u16 fg, bg; - fg = ((info->cmap.red[fbcursor->image.fg_color] & 0xf800))| - ((info->cmap.green[fbcursor->image.fg_color] & 0xfc00) >> 5)| + fg = ((info->cmap.red[fbcursor->image.fg_color] & 0xf800)) | + ((info->cmap.green[fbcursor->image.fg_color] & 0xfc00) >> 5) | ((info->cmap.blue[fbcursor->image.fg_color] & 0xf800) >> 11); - bg = ((info->cmap.red[fbcursor->image.bg_color] & 0xf800))| - ((info->cmap.green[fbcursor->image.bg_color] & 0xfc00) >> 5)| + bg = ((info->cmap.red[fbcursor->image.bg_color] & 0xf800)) | + ((info->cmap.green[fbcursor->image.bg_color] & 0xfc00) >> 5) | ((info->cmap.blue[fbcursor->image.bg_color] & 0xf800) >> 11); cursor->setColor(cursor, fg, bg); } - if (fbcursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) { cursor->setData(cursor, fbcursor->rop, @@ -188,14 +182,17 @@ static void lynxfb_ops_fillrect(struct fb_info *info, par = info->par; share = par->share; - /* each time 2d function begin to work,below three variable always need - * be set, seems we can put them together in some place */ + /* + * each time 2d function begin to work,below three variable always need + * be set, seems we can put them together in some place + */ base = par->crtc.oScreen; pitch = info->fix.line_length; Bpp = info->var.bits_per_pixel >> 3; - color = (Bpp == 1)?region->color:((u32 *)info->pseudo_palette)[region->color]; - rop = (region->rop != ROP_COPY) ? HW_ROP2_XOR:HW_ROP2_COPY; + color = (Bpp == 1) ? region->color : + ((u32 *)info->pseudo_palette)[region->color]; + rop = (region->rop != ROP_COPY) ? HW_ROP2_XOR : HW_ROP2_COPY; /* * If not use spin_lock,system will die if user load driver @@ -223,8 +220,10 @@ static void lynxfb_ops_copyarea(struct fb_info *info, par = info->par; share = par->share; - /* each time 2d function begin to work,below three variable always need - * be set, seems we can put them together in some place */ + /* + * each time 2d function begin to work,below three variable always need + * be set, seems we can put them together in some place + */ base = par->crtc.oScreen; pitch = info->fix.line_length; Bpp = info->var.bits_per_pixel >> 3; @@ -254,28 +253,29 @@ static void lynxfb_ops_imageblit(struct fb_info *info, par = info->par; share = par->share; - /* each time 2d function begin to work,below three variable always need - * be set, seems we can put them together in some place */ + /* + * each time 2d function begin to work,below three variable always need + * be set, seems we can put them together in some place + */ base = par->crtc.oScreen; pitch = info->fix.line_length; Bpp = info->var.bits_per_pixel >> 3; - if (image->depth == 1) { - if (info->fix.visual == FB_VISUAL_TRUECOLOR || - info->fix.visual == FB_VISUAL_DIRECTCOLOR) { - fgcol = ((u32 *)info->pseudo_palette)[image->fg_color]; - bgcol = ((u32 *)info->pseudo_palette)[image->bg_color]; - } else { - fgcol = image->fg_color; - bgcol = image->bg_color; - } - goto _do_work; - } /* TODO: Implement hardware acceleration for image->depth > 1 */ - cfb_imageblit(info, image); - return; + if (image->depth != 1) { + cfb_imageblit(info, image); + return; + } + + if (info->fix.visual == FB_VISUAL_TRUECOLOR || + info->fix.visual == FB_VISUAL_DIRECTCOLOR) { + fgcol = ((u32 *)info->pseudo_palette)[image->fg_color]; + bgcol = ((u32 *)info->pseudo_palette)[image->bg_color]; + } else { + fgcol = image->fg_color; + bgcol = image->bg_color; + } -_do_work: /* * If not use spin_lock, system will die if user load driver * and immediately unload driver frequently (dual) @@ -284,7 +284,7 @@ _do_work: spin_lock(&share->slock); share->accel.de_imageblit(&share->accel, - image->data, image->width>>3, 0, + image->data, image->width >> 3, 0, base, pitch, Bpp, image->dx, image->dy, image->width, image->height, @@ -298,18 +298,13 @@ static int lynxfb_ops_pan_display(struct fb_var_screeninfo *var, { struct lynxfb_par *par; struct lynxfb_crtc *crtc; - int ret; - if (!info) return -EINVAL; - ret = 0; par = info->par; crtc = &par->crtc; - ret = crtc->proc_panDisplay(crtc, var, info); - - return ret; + return crtc->proc_panDisplay(crtc, var, info); } static int lynxfb_ops_set_par(struct fb_info *info) @@ -340,9 +335,10 @@ static int lynxfb_ops_set_par(struct fb_info *info) fix->line_length = line_length; pr_info("fix->line_length = %d\n", fix->line_length); - /* var->red,green,blue,transp are need to be set by driver + /* + * var->red,green,blue,transp are need to be set by driver * and these data should be set before setcolreg routine - * */ + */ switch (var->bits_per_pixel) { case 8: @@ -466,7 +462,6 @@ static int lynxfb_resume(struct pci_dev *pdev) int ret; - ret = 0; share = pci_get_drvdata(pdev); @@ -478,7 +473,6 @@ static int lynxfb_resume(struct pci_dev *pdev) return ret; } - if (pdev->dev.power.power_state.event != PM_EVENT_FREEZE) { pci_restore_state(pdev); ret = pci_enable_device(pdev); @@ -493,7 +487,6 @@ static int lynxfb_resume(struct pci_dev *pdev) hw_sm750_inithw(share, pdev); - info = share->fbinfo[0]; if (info) { @@ -518,7 +511,6 @@ static int lynxfb_resume(struct pci_dev *pdev) fb_set_suspend(info, 0); } - console_unlock(); return ret; } @@ -534,7 +526,6 @@ static int lynxfb_ops_check_var(struct fb_var_screeninfo *var, int ret; resource_size_t request; - par = info->par; crtc = &par->crtc; output = &par->output; @@ -546,7 +537,6 @@ static int lynxfb_ops_check_var(struct fb_var_screeninfo *var, var->yres, var->bits_per_pixel); - switch (var->bits_per_pixel) { case 8: case 16: @@ -617,7 +607,6 @@ exit: return ret; } - static int lynxfb_ops_setcolreg(unsigned regno, unsigned red, unsigned green, @@ -652,7 +641,6 @@ static int lynxfb_ops_setcolreg(unsigned regno, goto exit; } - if (info->fix.visual == FB_VISUAL_TRUECOLOR && regno < 256) { u32 val; @@ -699,7 +687,8 @@ static int sm750fb_set_drv(struct lynxfb_par *par) output = &par->output; crtc = &par->crtc; - crtc->vidmem_size = (share->dual)?share->vidmem_size>>1:share->vidmem_size; + crtc->vidmem_size = (share->dual) ? share->vidmem_size >> 1 : + share->vidmem_size; /* setup crtc and output member */ spec_share->hwCursor = g_hwcursor; @@ -716,10 +705,12 @@ static int sm750fb_set_drv(struct lynxfb_par *par) output->proc_setMode = hw_sm750_output_setMode; output->proc_checkMode = hw_sm750_output_checkMode; - output->proc_setBLANK = (share->revid == SM750LE_REVISION_ID)?hw_sm750le_setBLANK:hw_sm750_setBLANK; + output->proc_setBLANK = (share->revid == SM750LE_REVISION_ID) ? + hw_sm750le_setBLANK : hw_sm750_setBLANK; output->clear = hw_sm750_output_clear; /* chip specific phase */ - share->accel.de_wait = (share->revid == SM750LE_REVISION_ID)?hw_sm750le_deWait : hw_sm750_deWait; + share->accel.de_wait = (share->revid == SM750LE_REVISION_ID) ? + hw_sm750le_deWait : hw_sm750_deWait; switch (spec_share->state.dataflow) { case sm750_simul_pri: output->paths = sm750_pnc; @@ -782,7 +773,6 @@ static struct fb_ops lynxfb_ops = { .fb_cursor = lynxfb_ops_cursor, }; - static int lynxfb_set_fbinfo(struct fb_info *info, int index) { int i; @@ -803,7 +793,6 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index) "kernel HELPERS prepared vesa_modes", }; - static const char *fixId[2] = { "sm750_fb1", "sm750_fb2", }; @@ -824,15 +813,16 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index) sm750fb_set_drv(par); lynxfb_ops.fb_pan_display = lynxfb_ops_pan_display; - - /* set current cursor variable and proc pointer, - * must be set after crtc member initialized */ + /* + * set current cursor variable and proc pointer, + * must be set after crtc member initialized + */ crtc->cursor.offset = crtc->oScreen + crtc->vidmem_size - 1024; crtc->cursor.mmio = share->pvReg + 0x800f0 + (int)crtc->channel * 0x140; pr_info("crtc->cursor.mmio = %p\n", crtc->cursor.mmio); crtc->cursor.maxH = crtc->cursor.maxW = 64; - crtc->cursor.size = crtc->cursor.maxH*crtc->cursor.maxW*2/8; + crtc->cursor.size = crtc->cursor.maxH * crtc->cursor.maxW * 2 / 8; crtc->cursor.disable = hw_cursor_disable; crtc->cursor.enable = hw_cursor_enable; crtc->cursor.setColor = hw_cursor_setColor; @@ -841,7 +831,6 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index) crtc->cursor.setData = hw_cursor_setData; crtc->cursor.vstart = share->pvMem + crtc->cursor.offset; - crtc->cursor.share = share; memset_io(crtc->cursor.vstart, 0, crtc->cursor.size); if (!g_hwcursor) { @@ -849,7 +838,6 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index) crtc->cursor.disable(&crtc->cursor); } - /* set info->fbops, must be set before fb_find_mode */ if (!share->accel_off) { /* use 2d acceleration */ @@ -865,7 +853,6 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index) g_fbmode[index] = g_fbmode[0]; } - for (i = 0; i < 3; i++) { ret = fb_find_mode(var, info, g_fbmode[index], @@ -917,13 +904,13 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index) /* set info */ line_length = PADDING(crtc->line_pad, - (var->xres_virtual * var->bits_per_pixel/8)); + (var->xres_virtual * var->bits_per_pixel / 8)); info->pseudo_palette = &par->pseudo_palette[0]; info->screen_base = crtc->vScreen; pr_debug("screen_base vaddr = %p\n", info->screen_base); info->screen_size = line_length * var->yres_virtual; - info->flags = FBINFO_FLAG_DEFAULT|0; + info->flags = FBINFO_FLAG_DEFAULT | 0; /* set info->fix */ fix->type = FB_TYPE_PACKED_PIXELS; @@ -935,15 +922,15 @@ static int lynxfb_set_fbinfo(struct fb_info *info, int index) strlcpy(fix->id, fixId[index], sizeof(fix->id)); - fix->smem_start = crtc->oScreen + share->vidmem_start; pr_info("fix->smem_start = %lx\n", fix->smem_start); - /* according to mmap experiment from user space application, + /* + * according to mmap experiment from user space application, * fix->mmio_len should not larger than virtual size * (xres_virtual x yres_virtual x ByPP) * Below line maybe buggy when user mmap fb dev node and write * data into the bound over virtual size - * */ + */ fix->smem_len = crtc->vidmem_size; pr_info("fix->smem_len = %x\n", fix->smem_len); info->screen_size = fix->smem_len; @@ -998,7 +985,6 @@ static void sm750fb_setup(struct lynx_share *share, char *src) #endif int swap; - spec_share = container_of(share, struct sm750_share, share); #ifdef CAP_EXPENSIION exp_res = NULL; @@ -1096,15 +1082,16 @@ static int lynxfb_pci_probe(struct pci_dev *pdev, size_t spec_offset = 0; int fbidx; - /* enable device */ if (pci_enable_device(pdev)) { pr_err("can not enable device.\n"); goto err_enable; } - /* though offset of share in sm750_share is 0, - * we use this marcro as the same */ + /* + * though offset of share in sm750_share is 0, + * we use this marcro as the same + */ spec_offset = offsetof(struct sm750_share, share); spec_share = kzalloc(sizeof(*spec_share), GFP_KERNEL); @@ -1128,10 +1115,12 @@ static int lynxfb_pci_probe(struct pci_dev *pdev, spin_lock_init(&share->slock); if (!share->accel_off) { - /* hook deInit and 2d routines, notes that below hw_xxx + /* + * hook deInit and 2d routines, notes that below hw_xxx * routine can work on most of lynx chips * if some chip need specific function, - * please hook it in smXXX_set_drv routine */ + * please hook it in smXXX_set_drv routine + */ share->accel.de_init = hw_de_init; share->accel.de_fillrect = hw_fillrect; share->accel.de_copyarea = hw_copyarea; @@ -1268,7 +1257,6 @@ static int __init lynxfb_setup(char *options) int len; char *opt, *tmp; - if (!options || !*options) { pr_warn("no options.\n"); return 0; @@ -1283,14 +1271,15 @@ static int __init lynxfb_setup(char *options) tmp = g_settings; - /* Notes: - char * strsep(char **s,const char * ct); - @s: the string to be searched - @ct :the characters to search for - - strsep() updates @options to pointer after the first found token - it also returns the pointer ahead the token. - */ + /* + * Notes: + * char * strsep(char **s,const char * ct); + * @s: the string to be searched + * @ct :the characters to search for + * + * strsep() updates @options to pointer after the first found token + * it also returns the pointer ahead the token. + */ while ((opt = strsep(&options, ":")) != NULL) { /* options that mean for any lynx chips are configured here */ if (!strncmp(opt, "noaccel", strlen("noaccel"))) @@ -1332,7 +1321,6 @@ static struct pci_driver lynxfb_driver = { #endif }; - static int __init lynxfb_init(void) { char *option; diff --git a/drivers/staging/sm7xxfb/Kconfig b/drivers/staging/sm7xxfb/Kconfig deleted file mode 100644 index e2922ae3a3ee..000000000000 --- a/drivers/staging/sm7xxfb/Kconfig +++ /dev/null @@ -1,13 +0,0 @@ -config FB_SM7XX - tristate "Silicon Motion SM7XX framebuffer support" - depends on FB && PCI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - Frame buffer driver for the Silicon Motion SM710, SM712, SM721 - and SM722 chips. - - This driver is also available as a module. The module will be - called sm7xxfb. If you want to compile it as a module, say M - here and read <file:Documentation/kbuild/modules.txt>. diff --git a/drivers/staging/sm7xxfb/Makefile b/drivers/staging/sm7xxfb/Makefile deleted file mode 100644 index 48f471cf9f36..000000000000 --- a/drivers/staging/sm7xxfb/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_FB_SM7XX) += sm7xxfb.o diff --git a/drivers/staging/sm7xxfb/TODO b/drivers/staging/sm7xxfb/TODO deleted file mode 100644 index 7cb0b242f204..000000000000 --- a/drivers/staging/sm7xxfb/TODO +++ /dev/null @@ -1,12 +0,0 @@ -TODO: -- Dual head support -- 2D acceleration support -- use kernel coding style -- refine the code and remove unused code -- move it to drivers/video/fbdev/sm7xxfb.c - -Please send any patches to - Greg Kroah-Hartman <greg@kroah.com> - Sudip Mukherjee <sudipm.mukherjee@gmail.com> - Teddy Wang <teddy.wang@siliconmotion.com> - Sudip Mukherjee <sudip@vectorindia.org> diff --git a/drivers/staging/unisys/include/channel_guid.h b/drivers/staging/unisys/include/channel_guid.h index 706363fc3e9a..17cb499cb53c 100644 --- a/drivers/staging/unisys/include/channel_guid.h +++ b/drivers/staging/unisys/include/channel_guid.h @@ -17,35 +17,31 @@ * CHANNEL Guids */ -/* Used in IOChannel - * {414815ed-c58c-11da-95a9-00e08161165f} - */ +/* {414815ed-c58c-11da-95a9-00e08161165f} */ #define SPAR_VHBA_CHANNEL_PROTOCOL_UUID \ UUID_LE(0x414815ed, 0xc58c, 0x11da, \ 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f) static const uuid_le spar_vhba_channel_protocol_uuid = SPAR_VHBA_CHANNEL_PROTOCOL_UUID; +#define SPAR_VHBA_CHANNEL_PROTOCOL_UUID_STR \ + "414815ed-c58c-11da-95a9-00e08161165f" -/* Used in IOChannel - * {8cd5994d-c58e-11da-95a9-00e08161165f} - */ +/* {8cd5994d-c58e-11da-95a9-00e08161165f} */ #define SPAR_VNIC_CHANNEL_PROTOCOL_UUID \ UUID_LE(0x8cd5994d, 0xc58e, 0x11da, \ 0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f) static const uuid_le spar_vnic_channel_protocol_uuid = SPAR_VNIC_CHANNEL_PROTOCOL_UUID; +#define SPAR_VNIC_CHANNEL_PROTOCOL_UUID_STR \ + "8cd5994d-c58e-11da-95a9-00e08161165f" -/* Used in IOChannel - * {72120008-4AAB-11DC-8530-444553544200} - */ +/* {72120008-4AAB-11DC-8530-444553544200} */ #define SPAR_SIOVM_UUID \ UUID_LE(0x72120008, 0x4AAB, 0x11DC, \ 0x85, 0x30, 0x44, 0x45, 0x53, 0x54, 0x42, 0x00) static const uuid_le spar_siovm_uuid = SPAR_SIOVM_UUID; -/* Used in visornoop/visornoop_main.c - * {5b52c5ac-e5f5-4d42-8dff-429eaecd221f} - */ +/* {5b52c5ac-e5f5-4d42-8dff-429eaecd221f} */ #define SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID \ UUID_LE(0x5b52c5ac, 0xe5f5, 0x4d42, \ 0x8d, 0xff, 0x42, 0x9e, 0xae, 0xcd, 0x22, 0x1f) @@ -53,9 +49,7 @@ static const uuid_le spar_siovm_uuid = SPAR_SIOVM_UUID; static const uuid_le spar_controldirector_channel_protocol_uuid = SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID; -/* Used in visorchipset/visorchipset_main.c - * {B4E79625-AEDE-4EAA-9E11-D3EDDCD4504C} - */ +/* {b4e79625-aede-4eAA-9e11-D3eddcd4504c} */ #define SPAR_DIAG_POOL_CHANNEL_PROTOCOL_UUID \ UUID_LE(0xb4e79625, 0xaede, 0x4eaa, \ 0x9e, 0x11, 0xd3, 0xed, 0xdc, 0xd4, 0x50, 0x4c) diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h index a0144c6a8ad1..9235536fa75f 100644 --- a/drivers/staging/unisys/include/visorbus.h +++ b/drivers/staging/unisys/include/visorbus.h @@ -201,6 +201,8 @@ bool visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg); bool visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg); +bool visorchannel_signalempty(struct visorchannel *channel, u32 queue); + int visorchannel_signalqueue_slots_avail(struct visorchannel *channel, u32 queue); int visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue); diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index 403c13b7864b..cc4a0292c287 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -69,6 +69,38 @@ static const struct attribute_group *visorbus_bus_groups[] = { NULL, }; +/* + * DEVICE type attributes + * + * The modalias file will contain the guid of the device. + */ +static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct visor_device *vdev; + uuid_le guid; + + vdev = to_visor_device(dev); + guid = visorchannel_get_uuid(vdev->visorchannel); + return snprintf(buf, PAGE_SIZE, "visorbus:%pUl\n", &guid); +} +static DEVICE_ATTR_RO(modalias); + +static struct attribute *visorbus_dev_attrs[] = { + &dev_attr_modalias.attr, + NULL, +}; + +/* sysfs example for bridge-only sysfs files using device_type's */ +static const struct attribute_group visorbus_dev_group = { + .attrs = visorbus_dev_attrs, +}; + +const struct attribute_group *visorbus_dev_groups[] = { + &visorbus_dev_group, + NULL, +}; + /** This describes the TYPE of bus. * (Don't confuse this with an INSTANCE of the bus.) */ @@ -76,6 +108,7 @@ struct bus_type visorbus_type = { .name = "visorbus", .match = visorbus_match, .uevent = visorbus_uevent, + .dev_groups = visorbus_dev_groups, .bus_groups = visorbus_bus_groups, }; @@ -128,7 +161,13 @@ static LIST_HEAD(list_all_device_instances); static int visorbus_uevent(struct device *xdev, struct kobj_uevent_env *env) { - if (add_uevent_var(env, "VERSION=%s", VERSION)) + struct visor_device *dev; + uuid_le guid; + + dev = to_visor_device(xdev); + guid = visorchannel_get_uuid(dev->visorchannel); + + if (add_uevent_var(env, "MODALIAS=visorbus:%pUl", &guid)) return -ENOMEM; return 0; } @@ -477,7 +516,7 @@ static struct attribute_group channel_attr_grp = { .attrs = channel_attrs, }; -static const struct attribute_group *visorbus_dev_groups[] = { +static const struct attribute_group *visorbus_channel_groups[] = { &channel_attr_grp, NULL }; @@ -936,7 +975,7 @@ create_visor_device(struct visor_device *dev) sema_init(&dev->visordriver_callback_lock, 1); /* unlocked */ dev->device.bus = &visorbus_type; - dev->device.groups = visorbus_dev_groups; + dev->device.groups = visorbus_channel_groups; device_initialize(&dev->device); dev->device.release = visorbus_release_device; /* keep a reference just for us (now 2) */ diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index 242246492b7a..6da7e49a6627 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -430,6 +430,27 @@ visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg) } EXPORT_SYMBOL_GPL(visorchannel_signalremove); +bool +visorchannel_signalempty(struct visorchannel *channel, u32 queue) +{ + unsigned long flags = 0; + struct signal_queue_header sig_hdr; + bool rc = false; + + if (channel->needs_lock) + spin_lock_irqsave(&channel->remove_lock, flags); + + if (!sig_read_header(channel, queue, &sig_hdr)) + rc = true; + if (sig_hdr.head == sig_hdr.tail) + rc = true; + if (channel->needs_lock) + spin_unlock_irqrestore(&channel->remove_lock, flags); + + return rc; +} +EXPORT_SYMBOL_GPL(visorchannel_signalempty); + static bool signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg) { diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index c28a34767552..63d90f599158 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -19,15 +19,16 @@ */ #include <linux/debugfs.h> -#include <linux/netdevice.h> #include <linux/etherdevice.h> -#include <linux/skbuff.h> +#include <linux/netdevice.h> #include <linux/kthread.h> +#include <linux/skbuff.h> +#include <linux/rtnetlink.h> #include "visorbus.h" #include "iochannel.h" -#define VISORNIC_INFINITE_RESPONSE_WAIT 0 +#define VISORNIC_INFINITE_RSP_WAIT 0 #define VISORNICSOPENMAX 32 #define MAXDEVICES 16384 @@ -60,7 +61,6 @@ static const struct file_operations debugfs_enable_ints_fops = { .write = enable_ints_write, }; -static struct workqueue_struct *visornic_serverdown_workqueue; static struct workqueue_struct *visornic_timeout_reset_workqueue; /* GUIDS for director channel type supported by this driver. */ @@ -89,12 +89,6 @@ static struct visor_driver visornic_driver = { .channel_interrupt = NULL, }; -struct visor_thread_info { - struct task_struct *task; - struct completion has_stopped; - int id; -}; - struct chanstat { unsigned long got_rcv; unsigned long got_enbdisack; @@ -103,6 +97,7 @@ struct chanstat { unsigned long sent_enbdis; unsigned long sent_promisc; unsigned long sent_post; + unsigned long sent_post_failed; unsigned long sent_xmit; unsigned long reject_count; unsigned long extra_rcvbufs_sent; @@ -110,7 +105,6 @@ struct chanstat { struct visornic_devdata { int devnum; - int thread_wait_ms; unsigned short enabled; /* 0 disabled 1 enabled to receive */ unsigned short enab_dis_acked; /* NET_RCV_ENABLE/DISABLE acked by * IOPART @@ -135,20 +129,20 @@ struct visornic_devdata { atomic_t num_rcvbuf_in_iovm; unsigned long alloc_failed_in_if_needed_cnt; unsigned long alloc_failed_in_repost_rtn_cnt; - int max_outstanding_net_xmits; /* absolute max number of outstanding - * xmits - should never hit this - */ - int upper_threshold_net_xmits; /* high water mark for calling - * netif_stop_queue() - */ - int lower_threshold_net_xmits; /* high water mark for calling - * netif_wake_queue() - */ + unsigned long max_outstanding_net_xmits; /* absolute max number of + * outstanding xmits - should + * never hit this + */ + unsigned long upper_threshold_net_xmits; /* high water mark for + * calling netif_stop_queue() + */ + unsigned long lower_threshold_net_xmits; /* high water mark for calling + * netif_wake_queue() + */ struct sk_buff_head xmitbufhead; /* xmitbufhead is the head of the * xmit buffer list that have been * sent to the IOPART end */ - struct work_struct serverdown_completion; visorbus_state_complete_func server_down_complete_func; struct work_struct timeout_reset; struct uiscmdrsp *cmdrsp_rcv; /* cmdrsp_rcv is used for @@ -162,7 +156,6 @@ struct visornic_devdata { bool server_change_state; /* Processing SERVER_CHANGESTATE msg */ bool going_away; /* device is being torn down */ struct dentry *eth_debugfs_dir; - struct visor_thread_info threadinfo; u64 interrupts_rcvd; u64 interrupts_notme; u64 interrupts_disabled; @@ -194,16 +187,19 @@ struct visornic_devdata { int queuefullmsg_logged; struct chanstat chstat; + struct timer_list irq_poll_timer; + struct napi_struct napi; + struct uiscmdrsp cmdrsp[SIZEOF_CMDRSP]; }; -/* array of open devices maintained by open() and close() */ -static struct net_device *num_visornic_open[VISORNICSOPENMAX]; /* List of all visornic_devdata structs, * linked via the list_all member */ static LIST_HEAD(list_all_devices); static DEFINE_SPINLOCK(lock_all_devices); +static int visornic_poll(struct napi_struct *napi, int budget); +static void poll_for_irq(unsigned long v); /** * visor_copy_fragsinfo_from_skb( @@ -223,9 +219,25 @@ visor_copy_fragsinfo_from_skb(struct sk_buff *skb, unsigned int firstfraglen, struct phys_info frags[]) { unsigned int count = 0, ii, size, offset = 0, numfrags; + unsigned int total_count; numfrags = skb_shinfo(skb)->nr_frags; + /* + * Compute the number of fragments this skb has, and if its more than + * frag array can hold, linearize the skb + */ + total_count = numfrags + (firstfraglen / PI_PAGE_SIZE); + if (firstfraglen % PI_PAGE_SIZE) + total_count++; + + if (total_count > frags_max) { + if (skb_linearize(skb)) + return -EINVAL; + numfrags = skb_shinfo(skb)->nr_frags; + firstfraglen = 0; + } + while (firstfraglen) { if (count == frags_max) return -EINVAL; @@ -256,8 +268,16 @@ visor_copy_fragsinfo_from_skb(struct sk_buff *skb, unsigned int firstfraglen, page_offset, skb_shinfo(skb)->frags[ii]. size, count, frags_max, frags); - if (!count) - return -EIO; + /* + * add_physinfo_entries only returns + * zero if the frags array is out of room + * That should never happen because we + * fail above, if count+numfrags > frags_max. + * Given that theres no recovery mechanism from putting + * half a packet in the I/O channel, panic here as this + * should never happen + */ + BUG_ON(!count); } } if (skb_shinfo(skb)->frag_list) { @@ -279,224 +299,15 @@ visor_copy_fragsinfo_from_skb(struct sk_buff *skb, unsigned int firstfraglen, return count; } -/** - * visort_thread_start - starts thread for the device - * @thrinfo: The thread to start - * @threadfn: Function the thread starts - * @thrcontext: Context to pass to the thread, i.e. devdata - * @name: string describing name of thread - * - * Starts a thread for the device, currently only thread is - * process_incoming_rsps - * Returns 0 on success; - */ -static int visor_thread_start(struct visor_thread_info *thrinfo, - int (*threadfn)(void *), - void *thrcontext, char *name) -{ - /* used to stop the thread */ - init_completion(&thrinfo->has_stopped); - thrinfo->task = kthread_run(threadfn, thrcontext, name); - if (IS_ERR(thrinfo->task)) { - pr_debug("%s failed (%ld)\n", - __func__, PTR_ERR(thrinfo->task)); - thrinfo->id = 0; - return -EINVAL; - } - thrinfo->id = thrinfo->task->pid; - return 0; -} - -/** - * visor_thread_stop - stop a thread for the device - * @thrinfo: The thread to stop - * - * Stop the thread and wait for completion for a minute - * Returns void. - */ -static void visor_thread_stop(struct visor_thread_info *thrinfo) -{ - if (!thrinfo->id) - return; /* thread not running */ - - kthread_stop(thrinfo->task); - /* give up if the thread has NOT died in 1 minute */ - if (wait_for_completion_timeout(&thrinfo->has_stopped, 60 * HZ)) - thrinfo->id = 0; -} - -/* DebugFS code */ -static ssize_t info_debugfs_read(struct file *file, char __user *buf, - size_t len, loff_t *offset) -{ - int i; - ssize_t bytes_read = 0; - int str_pos = 0; - struct visornic_devdata *devdata; - char *vbuf; - - if (len > MAX_BUF) - len = MAX_BUF; - vbuf = kzalloc(len, GFP_KERNEL); - if (!vbuf) - return -ENOMEM; - - /* for each vnic channel - * dump out channel specific data - */ - for (i = 0; i < VISORNICSOPENMAX; i++) { - if (!num_visornic_open[i]) - continue; - - devdata = netdev_priv(num_visornic_open[i]); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - "Vnic i = %d\n", i); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - "netdev = %s (0x%p), MAC Addr %pM\n", - num_visornic_open[i]->name, - num_visornic_open[i], - num_visornic_open[i]->dev_addr); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - "VisorNic Dev Info = 0x%p\n", devdata); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " num_rcv_bufs = %d\n", - devdata->num_rcv_bufs); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " max_oustanding_next_xmits = %d\n", - devdata->max_outstanding_net_xmits); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " upper_threshold_net_xmits = %d\n", - devdata->upper_threshold_net_xmits); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " lower_threshold_net_xmits = %d\n", - devdata->lower_threshold_net_xmits); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " queuefullmsg_logged = %d\n", - devdata->queuefullmsg_logged); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " chstat.got_rcv = %lu\n", - devdata->chstat.got_rcv); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " chstat.got_enbdisack = %lu\n", - devdata->chstat.got_enbdisack); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " chstat.got_xmit_done = %lu\n", - devdata->chstat.got_xmit_done); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " chstat.xmit_fail = %lu\n", - devdata->chstat.xmit_fail); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " chstat.sent_enbdis = %lu\n", - devdata->chstat.sent_enbdis); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " chstat.sent_promisc = %lu\n", - devdata->chstat.sent_promisc); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " chstat.sent_post = %lu\n", - devdata->chstat.sent_post); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " chstat.sent_xmit = %lu\n", - devdata->chstat.sent_xmit); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " chstat.reject_count = %lu\n", - devdata->chstat.reject_count); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " chstat.extra_rcvbufs_sent = %lu\n", - devdata->chstat.extra_rcvbufs_sent); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " n_rcv0 = %lu\n", devdata->n_rcv0); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " n_rcv1 = %lu\n", devdata->n_rcv1); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " n_rcv2 = %lu\n", devdata->n_rcv2); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " n_rcvx = %lu\n", devdata->n_rcvx); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " num_rcvbuf_in_iovm = %d\n", - atomic_read(&devdata->num_rcvbuf_in_iovm)); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " alloc_failed_in_if_needed_cnt = %lu\n", - devdata->alloc_failed_in_if_needed_cnt); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " alloc_failed_in_repost_rtn_cnt = %lu\n", - devdata->alloc_failed_in_repost_rtn_cnt); - /* str_pos += scnprintf(vbuf + str_pos, len - str_pos, - * " inner_loop_limit_reached_cnt = %lu\n", - * devdata->inner_loop_limit_reached_cnt); - */ - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " found_repost_rcvbuf_cnt = %lu\n", - devdata->found_repost_rcvbuf_cnt); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " repost_found_skb_cnt = %lu\n", - devdata->repost_found_skb_cnt); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " n_repost_deficit = %lu\n", - devdata->n_repost_deficit); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " bad_rcv_buf = %lu\n", - devdata->bad_rcv_buf); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " n_rcv_packets_not_accepted = %lu\n", - devdata->n_rcv_packets_not_accepted); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " interrupts_rcvd = %llu\n", - devdata->interrupts_rcvd); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " interrupts_notme = %llu\n", - devdata->interrupts_notme); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " interrupts_disabled = %llu\n", - devdata->interrupts_disabled); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " busy_cnt = %llu\n", - devdata->busy_cnt); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " flow_control_upper_hits = %llu\n", - devdata->flow_control_upper_hits); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " flow_control_lower_hits = %llu\n", - devdata->flow_control_lower_hits); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " thread_wait_ms = %d\n", - devdata->thread_wait_ms); - str_pos += scnprintf(vbuf + str_pos, len - str_pos, - " netif_queue = %s\n", - netif_queue_stopped(devdata->netdev) ? - "stopped" : "running"); - } - bytes_read = simple_read_from_buffer(buf, len, offset, vbuf, str_pos); - kfree(vbuf); - return bytes_read; -} - static ssize_t enable_ints_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { - char buf[4]; - int i, new_value; - struct visornic_devdata *devdata; - - if (count >= ARRAY_SIZE(buf)) - return -EINVAL; - - buf[count] = '\0'; - if (copy_from_user(buf, buffer, count)) - return -EFAULT; - - i = kstrtoint(buf, 10, &new_value); - if (i != 0) - return -EFAULT; - - /* set all counts to new_value usually 0 */ - for (i = 0; i < VISORNICSOPENMAX; i++) { - if (num_visornic_open[i]) { - devdata = netdev_priv(num_visornic_open[i]); - /* TODO update features bit in channel */ - } - } - + /* + * Don't want to break ABI here by having a debugfs + * file that no longer exists or is writable, so + * lets just make this a vestigual function + */ return count; } @@ -511,41 +322,22 @@ static ssize_t enable_ints_write(struct file *file, * Returns void. */ static void -visornic_serverdown_complete(struct work_struct *work) +visornic_serverdown_complete(struct visornic_devdata *devdata) { - struct visornic_devdata *devdata; struct net_device *netdev; - unsigned long flags; - int i = 0, count = 0; - devdata = container_of(work, struct visornic_devdata, - serverdown_completion); netdev = devdata->netdev; - /* Stop using datachan */ - visor_thread_stop(&devdata->threadinfo); + /* Stop polling for interrupts */ + del_timer_sync(&devdata->irq_poll_timer); - /* Inform Linux that the link is down */ - netif_carrier_off(netdev); - netif_stop_queue(netdev); + rtnl_lock(); + dev_close(netdev); + rtnl_unlock(); - /* Free the skb for XMITs that haven't been serviced by the server - * We shouldn't have to inform Linux about these IOs because they - * are "lost in the ethernet" - */ - skb_queue_purge(&devdata->xmitbufhead); - - spin_lock_irqsave(&devdata->priv_lock, flags); - /* free rcv buffers */ - for (i = 0; i < devdata->num_rcv_bufs; i++) { - if (devdata->rcvbuf[i]) { - kfree_skb(devdata->rcvbuf[i]); - devdata->rcvbuf[i] = NULL; - count++; - } - } atomic_set(&devdata->num_rcvbuf_in_iovm, 0); - spin_unlock_irqrestore(&devdata->priv_lock, flags); + devdata->chstat.sent_xmit = 0; + devdata->chstat.got_xmit_done = 0; if (devdata->server_down_complete_func) (*devdata->server_down_complete_func)(devdata->dev, 0); @@ -580,15 +372,15 @@ visornic_serverdown(struct visornic_devdata *devdata, } devdata->server_change_state = true; devdata->server_down_complete_func = complete_func; - queue_work(visornic_serverdown_workqueue, - &devdata->serverdown_completion); + spin_unlock_irqrestore(&devdata->priv_lock, flags); + visornic_serverdown_complete(devdata); } else if (devdata->server_change_state) { dev_dbg(&devdata->dev->device, "%s changing state\n", __func__); spin_unlock_irqrestore(&devdata->priv_lock, flags); return -EINVAL; - } - spin_unlock_irqrestore(&devdata->priv_lock, flags); + } else + spin_unlock_irqrestore(&devdata->priv_lock, flags); return 0; } @@ -647,11 +439,14 @@ post_skb(struct uiscmdrsp *cmdrsp, if ((cmdrsp->net.rcvpost.frag.pi_off + skb->len) <= PI_PAGE_SIZE) { cmdrsp->net.type = NET_RCV_POST; cmdrsp->cmdtype = CMD_NET_TYPE; - visorchannel_signalinsert(devdata->dev->visorchannel, + if (visorchannel_signalinsert(devdata->dev->visorchannel, IOCHAN_TO_IOPART, - cmdrsp); - atomic_inc(&devdata->num_rcvbuf_in_iovm); - devdata->chstat.sent_post++; + cmdrsp)) { + atomic_inc(&devdata->num_rcvbuf_in_iovm); + devdata->chstat.sent_post++; + } else { + devdata->chstat.sent_post_failed++; + } } } @@ -673,10 +468,10 @@ send_enbdis(struct net_device *netdev, int state, devdata->cmdrsp_rcv->net.enbdis.context = netdev; devdata->cmdrsp_rcv->net.type = NET_RCV_ENBDIS; devdata->cmdrsp_rcv->cmdtype = CMD_NET_TYPE; - visorchannel_signalinsert(devdata->dev->visorchannel, + if (visorchannel_signalinsert(devdata->dev->visorchannel, IOCHAN_TO_IOPART, - devdata->cmdrsp_rcv); - devdata->chstat.sent_enbdis++; + devdata->cmdrsp_rcv)) + devdata->chstat.sent_enbdis++; } /** @@ -698,9 +493,6 @@ visornic_disable_with_timeout(struct net_device *netdev, const int timeout) unsigned long flags; int wait = 0; - /* stop the transmit queue so nothing more can be transmitted */ - netif_stop_queue(netdev); - /* send a msg telling the other end we are stopping incoming pkts */ spin_lock_irqsave(&devdata->priv_lock, flags); devdata->enabled = 0; @@ -717,7 +509,7 @@ visornic_disable_with_timeout(struct net_device *netdev, const int timeout) * when it gets a disable. */ spin_lock_irqsave(&devdata->priv_lock, flags); - while ((timeout == VISORNIC_INFINITE_RESPONSE_WAIT) || + while ((timeout == VISORNIC_INFINITE_RSP_WAIT) || (wait < timeout)) { if (devdata->enab_dis_acked) break; @@ -746,10 +538,16 @@ visornic_disable_with_timeout(struct net_device *netdev, const int timeout) break; } } - /* we've set enabled to 0, so we can give up the lock. */ spin_unlock_irqrestore(&devdata->priv_lock, flags); + /* stop the transmit queue so nothing more can be transmitted */ + netif_stop_queue(netdev); + + napi_disable(&devdata->napi); + + skb_queue_purge(&devdata->xmitbufhead); + /* Free rcv buffers - other end has automatically unposed them on * disable */ @@ -760,13 +558,6 @@ visornic_disable_with_timeout(struct net_device *netdev, const int timeout) } } - /* remove references from array */ - for (i = 0; i < VISORNICSOPENMAX; i++) - if (num_visornic_open[i] == netdev) { - num_visornic_open[i] = NULL; - break; - } - return 0; } @@ -846,6 +637,7 @@ visornic_enable_with_timeout(struct net_device *netdev, const int timeout) spin_lock_irqsave(&devdata->priv_lock, flags); devdata->enabled = 1; + devdata->enab_dis_acked = 0; /* now we're ready, let's send an ENB to uisnic but until we get * an ACK back from uisnic, we'll drop the packets @@ -856,10 +648,11 @@ visornic_enable_with_timeout(struct net_device *netdev, const int timeout) /* send enable and wait for ack -- don't hold lock when sending enable * because if the queue is full, insert might sleep. */ + napi_enable(&devdata->napi); send_enbdis(netdev, 1, devdata); spin_lock_irqsave(&devdata->priv_lock, flags); - while ((timeout == VISORNIC_INFINITE_RESPONSE_WAIT) || + while ((timeout == VISORNIC_INFINITE_RSP_WAIT) || (wait < timeout)) { if (devdata->enab_dis_acked) break; @@ -882,15 +675,7 @@ visornic_enable_with_timeout(struct net_device *netdev, const int timeout) return -EIO; } - /* find an open slot in the array to save off VisorNic references - * for debug - */ - for (i = 0; i < VISORNICSOPENMAX; i++) { - if (!num_visornic_open[i]) { - num_visornic_open[i] = netdev; - break; - } - } + netif_start_queue(netdev); return 0; } @@ -913,20 +698,29 @@ visornic_timeout_reset(struct work_struct *work) devdata = container_of(work, struct visornic_devdata, timeout_reset); netdev = devdata->netdev; - netif_stop_queue(netdev); - response = visornic_disable_with_timeout(netdev, 100); + rtnl_lock(); + if (!netif_running(netdev)) { + rtnl_unlock(); + return; + } + + response = visornic_disable_with_timeout(netdev, + VISORNIC_INFINITE_RSP_WAIT); if (response) goto call_serverdown; - response = visornic_enable_with_timeout(netdev, 100); + response = visornic_enable_with_timeout(netdev, + VISORNIC_INFINITE_RSP_WAIT); if (response) goto call_serverdown; - netif_wake_queue(netdev); + + rtnl_unlock(); return; call_serverdown: visornic_serverdown(devdata, NULL); + rtnl_unlock(); } /** @@ -939,12 +733,7 @@ call_serverdown: static int visornic_open(struct net_device *netdev) { - visornic_enable_with_timeout(netdev, VISORNIC_INFINITE_RESPONSE_WAIT); - - /* start the interface's transmit queue, allowing it to accept - * packets for transmission - */ - netif_start_queue(netdev); + visornic_enable_with_timeout(netdev, VISORNIC_INFINITE_RSP_WAIT); return 0; } @@ -959,13 +748,59 @@ visornic_open(struct net_device *netdev) static int visornic_close(struct net_device *netdev) { - netif_stop_queue(netdev); - visornic_disable_with_timeout(netdev, VISORNIC_INFINITE_RESPONSE_WAIT); + visornic_disable_with_timeout(netdev, VISORNIC_INFINITE_RSP_WAIT); return 0; } /** + * devdata_xmits_outstanding - compute outstanding xmits + * @devdata: visornic_devdata for device + * + * Return value is the number of outstanding xmits. + */ +static unsigned long devdata_xmits_outstanding(struct visornic_devdata *devdata) +{ + if (devdata->chstat.sent_xmit >= devdata->chstat.got_xmit_done) + return devdata->chstat.sent_xmit - + devdata->chstat.got_xmit_done; + else + return (ULONG_MAX - devdata->chstat.got_xmit_done + + devdata->chstat.sent_xmit + 1); +} + +/** + * vnic_hit_high_watermark + * @devdata: indicates visornic device we are checking + * @high_watermark: max num of unacked xmits we will tolerate, + * before we will start throttling + * + * Returns true iff the number of unacked xmits sent to + * the IO partition is >= high_watermark. + */ +static inline bool vnic_hit_high_watermark(struct visornic_devdata *devdata, + ulong high_watermark) +{ + return (devdata_xmits_outstanding(devdata) >= high_watermark); +} + +/** + * vnic_hit_low_watermark + * @devdata: indicates visornic device we are checking + * @low_watermark: we will wait until the num of unacked xmits + * drops to this value or lower before we start + * transmitting again + * + * Returns true iff the number of unacked xmits sent to + * the IO partition is <= low_watermark. + */ +static inline bool vnic_hit_low_watermark(struct visornic_devdata *devdata, + ulong low_watermark) +{ + return (devdata_xmits_outstanding(devdata) <= low_watermark); +} + +/** * visornic_xmit - send a packet to the IO Partition * @skb: Packet to be sent * @netdev: net device the packet is being sent from @@ -975,7 +810,7 @@ visornic_close(struct net_device *netdev) * function is protected from concurrent calls by a spinlock xmit_lock * in the net_device struct, but as soon as the function returns it * can be called again. - * Returns NETDEV_TX_OK for success, NETDEV_TX_BUSY for error. + * Returns NETDEV_TX_OK. */ static int visornic_xmit(struct sk_buff *skb, struct net_device *netdev) @@ -994,7 +829,8 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev) devdata->busy_cnt++; dev_dbg(&netdev->dev, "%s busy - queue stopped\n", __func__); - return NETDEV_TX_BUSY; + kfree_skb(skb); + return NETDEV_TX_OK; } /* sk_buff struct is used to host network data throughout all the @@ -1015,7 +851,8 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev) dev_err(&netdev->dev, "%s busy - first frag too small (%d)\n", __func__, firstfraglen); - return NETDEV_TX_BUSY; + kfree_skb(skb); + return NETDEV_TX_OK; } if ((len < ETH_MIN_PACKET_SIZE) && @@ -1038,13 +875,8 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev) /* save the pointer to skb -- we'll need it for completion */ cmdrsp->net.buf = skb; - if (((devdata->chstat.sent_xmit >= devdata->chstat.got_xmit_done) && - (devdata->chstat.sent_xmit - devdata->chstat.got_xmit_done >= - devdata->max_outstanding_net_xmits)) || - ((devdata->chstat.sent_xmit < devdata->chstat.got_xmit_done) && - (ULONG_MAX - devdata->chstat.got_xmit_done + - devdata->chstat.sent_xmit >= - devdata->max_outstanding_net_xmits))) { + if (vnic_hit_high_watermark(devdata, + devdata->max_outstanding_net_xmits)) { /* too many NET_XMITs queued over to IOVM - need to wait */ devdata->chstat.reject_count++; @@ -1057,7 +889,8 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev) dev_dbg(&netdev->dev, "%s busy - waiting for iovm to catch up\n", __func__); - return NETDEV_TX_BUSY; + kfree_skb(skb); + return NETDEV_TX_OK; } if (devdata->queuefullmsg_logged) devdata->queuefullmsg_logged = 0; @@ -1094,12 +927,13 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev) visor_copy_fragsinfo_from_skb(skb, firstfraglen, MAX_PHYS_INFO, cmdrsp->net.xmt.frags); - if (cmdrsp->net.xmt.num_frags == -1) { + if (cmdrsp->net.xmt.num_frags < 0) { spin_unlock_irqrestore(&devdata->priv_lock, flags); devdata->busy_cnt++; dev_err(&netdev->dev, "%s busy - copy frags failed\n", __func__); - return NETDEV_TX_BUSY; + kfree_skb(skb); + return NETDEV_TX_OK; } if (!visorchannel_signalinsert(devdata->dev->visorchannel, @@ -1109,18 +943,13 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev) devdata->busy_cnt++; dev_dbg(&netdev->dev, "%s busy - signalinsert failed\n", __func__); - return NETDEV_TX_BUSY; + kfree_skb(skb); + return NETDEV_TX_OK; } /* Track the skbs that have been sent to the IOVM for XMIT */ skb_queue_head(&devdata->xmitbufhead, skb); - /* set the last transmission start time - * linux doc says: Do not forget to update netdev->trans_start to - * jiffies after each new tx packet is given to the hardware. - */ - netdev->trans_start = jiffies; - /* update xmt stats */ devdata->net_stats.tx_packets++; devdata->net_stats.tx_bytes += skb->len; @@ -1129,13 +958,8 @@ visornic_xmit(struct sk_buff *skb, struct net_device *netdev) /* check to see if we have hit the high watermark for * netif_stop_queue() */ - if (((devdata->chstat.sent_xmit >= devdata->chstat.got_xmit_done) && - (devdata->chstat.sent_xmit - devdata->chstat.got_xmit_done >= - devdata->upper_threshold_net_xmits)) || - ((devdata->chstat.sent_xmit < devdata->chstat.got_xmit_done) && - (ULONG_MAX - devdata->chstat.got_xmit_done + - devdata->chstat.sent_xmit >= - devdata->upper_threshold_net_xmits))) { + if (vnic_hit_high_watermark(devdata, + devdata->upper_threshold_net_xmits)) { /* too many NET_XMITs queued over to IOVM - need to wait */ netif_stop_queue(netdev); /* calling stop queue - call * netif_wake_queue() after lower @@ -1167,21 +991,6 @@ visornic_get_stats(struct net_device *netdev) } /** - * visornic_ioctl - ioctl function for netdevice. - * @netdev: netdevice - * @ifr: ignored - * @cmd: ignored - * - * Currently not supported. - * Returns EOPNOTSUPP - */ -static int -visornic_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - return -EOPNOTSUPP; -} - -/** * visornic_change_mtu - changes mtu of device. * @netdev: netdevice * @new_mtu: value of new mtu @@ -1336,7 +1145,6 @@ repost_return(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata, devdata->bad_rcv_buf++; } } - atomic_dec(&devdata->usage); return status; } @@ -1348,18 +1156,16 @@ repost_return(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata, * it up the stack. * Returns void */ -static void +static int visornic_rx(struct uiscmdrsp *cmdrsp) { struct visornic_devdata *devdata; struct sk_buff *skb, *prev, *curr; struct net_device *netdev; - int cc, currsize, off, status; + int cc, currsize, off; struct ethhdr *eth; unsigned long flags; -#ifdef DEBUG - struct phys_info testfrags[MAX_PHYS_INFO]; -#endif + int rx_count = 0; /* post new rcv buf to the other end using the cmdrsp we have at hand * post it without holding lock - but we'll use the signal lock to @@ -1369,18 +1175,6 @@ visornic_rx(struct uiscmdrsp *cmdrsp) skb = cmdrsp->net.buf; netdev = skb->dev; - if (!netdev) { - /* We must have previously downed this network device and - * this skb and device is no longer valid. This also means - * the skb reference was removed from devdata->rcvbuf so no - * need to search for it. - * All we can do is free the skb and return. - * Note: We crash if we try to log this here. - */ - kfree_skb(skb); - return; - } - devdata = netdev_priv(netdev); spin_lock_irqsave(&devdata->priv_lock, flags); @@ -1390,10 +1184,6 @@ visornic_rx(struct uiscmdrsp *cmdrsp) devdata->net_stats.rx_packets++; devdata->net_stats.rx_bytes = skb->len; - atomic_inc(&devdata->usage); /* don't want a close to happen before - * we're done here - */ - /* set length to how much was ACTUALLY received - * NOTE: rcv_done_len includes actual length of data rcvd * including ethhdr @@ -1407,7 +1197,7 @@ visornic_rx(struct uiscmdrsp *cmdrsp) */ spin_unlock_irqrestore(&devdata->priv_lock, flags); repost_return(cmdrsp, devdata, skb, netdev); - return; + return rx_count; } spin_unlock_irqrestore(&devdata->priv_lock, flags); @@ -1426,7 +1216,7 @@ visornic_rx(struct uiscmdrsp *cmdrsp) if (repost_return(cmdrsp, devdata, skb, netdev) < 0) dev_err(&devdata->netdev->dev, "repost_return failed"); - return; + return rx_count; } /* length rcvd is greater than firstfrag in this skb rcv buf */ skb->tail += RCVPOST_BUF_SIZE; /* amount in skb->data */ @@ -1441,7 +1231,7 @@ visornic_rx(struct uiscmdrsp *cmdrsp) if (repost_return(cmdrsp, devdata, skb, netdev) < 0) dev_err(&devdata->netdev->dev, "repost_return failed"); - return; + return rx_count; } skb->tail += skb->len; skb->data_len = 0; /* nothing rcvd in frag_list */ @@ -1460,7 +1250,7 @@ visornic_rx(struct uiscmdrsp *cmdrsp) if (cmdrsp->net.rcv.rcvbuf[0] != skb) { if (repost_return(cmdrsp, devdata, skb, netdev) < 0) dev_err(&devdata->netdev->dev, "repost_return failed"); - return; + return rx_count; } if (cmdrsp->net.rcv.numrcvbufs > 1) { @@ -1486,29 +1276,12 @@ visornic_rx(struct uiscmdrsp *cmdrsp) curr->data_len = 0; off += currsize; } -#ifdef DEBUG /* assert skb->len == off */ if (skb->len != off) { - dev_err(&devdata->netdev->dev, - "%s something wrong; skb->len:%d != off:%d\n", - netdev->name, skb->len, off); - } - /* test code */ - cc = util_copy_fragsinfo_from_skb("rcvchaintest", skb, - RCVPOST_BUF_SIZE, - MAX_PHYS_INFO, testfrags); - if (cc != cmdrsp->net.rcv.numrcvbufs) { - dev_err(&devdata->netdev->dev, - "**** %s Something wrong; rcvd chain length %d different from one we calculated %d\n", - netdev->name, cmdrsp->net.rcv.numrcvbufs, cc); + netdev_err(devdata->netdev, + "something wrong; skb->len:%d != off:%d\n", + skb->len, off); } - for (i = 0; i < cc; i++) { - dev_inf(&devdata->netdev->dev, - "test:RCVPOST_BUF_SIZE:%d[%d] pfn:%llu off:0x%x len:%d\n", - RCVPOST_BUF_SIZE, i, testfrags[i].pi_pfn, - testfrags[i].pi_off, testfrags[i].pi_len); - } -#endif } /* set up packet's protocl type using ethernet header - this @@ -1560,10 +1333,11 @@ visornic_rx(struct uiscmdrsp *cmdrsp) /* drop packet - don't forward it up to OS */ devdata->n_rcv_packets_not_accepted++; repost_return(cmdrsp, devdata, skb, netdev); - return; + return rx_count; } while (0); - status = netif_rx(skb); + rx_count++; + netif_receive_skb(skb); /* netif_rx returns various values, but "in practice most drivers * ignore the return value */ @@ -1575,6 +1349,7 @@ visornic_rx(struct uiscmdrsp *cmdrsp) * new rcv buffer. */ repost_return(cmdrsp, devdata, skb, netdev); + return rx_count; } /** @@ -1636,12 +1411,163 @@ static const struct net_device_ops visornic_dev_ops = { .ndo_stop = visornic_close, .ndo_start_xmit = visornic_xmit, .ndo_get_stats = visornic_get_stats, - .ndo_do_ioctl = visornic_ioctl, .ndo_change_mtu = visornic_change_mtu, .ndo_tx_timeout = visornic_xmit_timeout, .ndo_set_rx_mode = visornic_set_multi, }; +/* DebugFS code */ +static ssize_t info_debugfs_read(struct file *file, char __user *buf, + size_t len, loff_t *offset) +{ + ssize_t bytes_read = 0; + int str_pos = 0; + struct visornic_devdata *devdata; + struct net_device *dev; + char *vbuf; + + if (len > MAX_BUF) + len = MAX_BUF; + vbuf = kzalloc(len, GFP_KERNEL); + if (!vbuf) + return -ENOMEM; + + /* for each vnic channel + * dump out channel specific data + */ + rcu_read_lock(); + for_each_netdev_rcu(current->nsproxy->net_ns, dev) { + /* + * Only consider netdevs that are visornic, and are open + */ + if ((dev->netdev_ops != &visornic_dev_ops) || + (!netif_queue_stopped(dev))) + continue; + + devdata = netdev_priv(dev); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + "netdev = %s (0x%p), MAC Addr %pM\n", + dev->name, + dev, + dev->dev_addr); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + "VisorNic Dev Info = 0x%p\n", devdata); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " num_rcv_bufs = %d\n", + devdata->num_rcv_bufs); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " max_oustanding_next_xmits = %lu\n", + devdata->max_outstanding_net_xmits); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " upper_threshold_net_xmits = %lu\n", + devdata->upper_threshold_net_xmits); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " lower_threshold_net_xmits = %lu\n", + devdata->lower_threshold_net_xmits); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " queuefullmsg_logged = %d\n", + devdata->queuefullmsg_logged); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " chstat.got_rcv = %lu\n", + devdata->chstat.got_rcv); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " chstat.got_enbdisack = %lu\n", + devdata->chstat.got_enbdisack); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " chstat.got_xmit_done = %lu\n", + devdata->chstat.got_xmit_done); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " chstat.xmit_fail = %lu\n", + devdata->chstat.xmit_fail); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " chstat.sent_enbdis = %lu\n", + devdata->chstat.sent_enbdis); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " chstat.sent_promisc = %lu\n", + devdata->chstat.sent_promisc); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " chstat.sent_post = %lu\n", + devdata->chstat.sent_post); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " chstat.sent_post_failed = %lu\n", + devdata->chstat.sent_post_failed); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " chstat.sent_xmit = %lu\n", + devdata->chstat.sent_xmit); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " chstat.reject_count = %lu\n", + devdata->chstat.reject_count); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " chstat.extra_rcvbufs_sent = %lu\n", + devdata->chstat.extra_rcvbufs_sent); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " n_rcv0 = %lu\n", devdata->n_rcv0); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " n_rcv1 = %lu\n", devdata->n_rcv1); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " n_rcv2 = %lu\n", devdata->n_rcv2); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " n_rcvx = %lu\n", devdata->n_rcvx); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " num_rcvbuf_in_iovm = %d\n", + atomic_read(&devdata->num_rcvbuf_in_iovm)); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " alloc_failed_in_if_needed_cnt = %lu\n", + devdata->alloc_failed_in_if_needed_cnt); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " alloc_failed_in_repost_rtn_cnt = %lu\n", + devdata->alloc_failed_in_repost_rtn_cnt); + /* str_pos += scnprintf(vbuf + str_pos, len - str_pos, + * " inner_loop_limit_reached_cnt = %lu\n", + * devdata->inner_loop_limit_reached_cnt); + */ + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " found_repost_rcvbuf_cnt = %lu\n", + devdata->found_repost_rcvbuf_cnt); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " repost_found_skb_cnt = %lu\n", + devdata->repost_found_skb_cnt); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " n_repost_deficit = %lu\n", + devdata->n_repost_deficit); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " bad_rcv_buf = %lu\n", + devdata->bad_rcv_buf); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " n_rcv_packets_not_accepted = %lu\n", + devdata->n_rcv_packets_not_accepted); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " interrupts_rcvd = %llu\n", + devdata->interrupts_rcvd); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " interrupts_notme = %llu\n", + devdata->interrupts_notme); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " interrupts_disabled = %llu\n", + devdata->interrupts_disabled); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " busy_cnt = %llu\n", + devdata->busy_cnt); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " flow_control_upper_hits = %llu\n", + devdata->flow_control_upper_hits); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " flow_control_lower_hits = %llu\n", + devdata->flow_control_lower_hits); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " netif_queue = %s\n", + netif_queue_stopped(devdata->netdev) ? + "stopped" : "running"); + str_pos += scnprintf(vbuf + str_pos, len - str_pos, + " xmits_outstanding = %lu\n", + devdata_xmits_outstanding(devdata)); + } + rcu_read_unlock(); + bytes_read = simple_read_from_buffer(buf, len, offset, vbuf, str_pos); + kfree(vbuf); + return bytes_read; +} + /** * send_rcv_posts_if_needed * @devdata: visornic device @@ -1695,15 +1621,15 @@ send_rcv_posts_if_needed(struct visornic_devdata *devdata) * Returns when response queue is empty or when the threadd stops. */ static void -drain_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata) +service_resp_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata, + int *rx_work_done) { unsigned long flags; struct net_device *netdev; - /* drain queue */ - while (1) { - /* TODO: CLIENT ACQUIRE -- Don't really need this at the - * moment */ + /* TODO: CLIENT ACQUIRE -- Don't really need this at the + * moment */ + for (;;) { if (!visorchannel_signalremove(devdata->dev->visorchannel, IOCHAN_FROM_IOPART, cmdrsp)) @@ -1713,7 +1639,7 @@ drain_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata) case NET_RCV: devdata->chstat.got_rcv++; /* process incoming packet */ - visornic_rx(cmdrsp); + *rx_work_done += visornic_rx(cmdrsp); break; case NET_XMIT_DONE: spin_lock_irqsave(&devdata->priv_lock, flags); @@ -1729,16 +1655,8 @@ drain_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata) * the lower watermark for * netif_wake_queue() */ - if (((devdata->chstat.sent_xmit >= - devdata->chstat.got_xmit_done) && - (devdata->chstat.sent_xmit - - devdata->chstat.got_xmit_done <= - devdata->lower_threshold_net_xmits)) || - ((devdata->chstat.sent_xmit < - devdata->chstat.got_xmit_done) && - (ULONG_MAX - devdata->chstat.got_xmit_done - + devdata->chstat.sent_xmit <= - devdata->lower_threshold_net_xmits))) { + if (vnic_hit_low_watermark(devdata, + devdata->lower_threshold_net_xmits)) { /* enough NET_XMITs completed * so can restart netif queue */ @@ -1789,50 +1707,51 @@ drain_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata) break; } /* cmdrsp is now available for reuse */ - - if (kthread_should_stop()) - break; } } +static int visornic_poll(struct napi_struct *napi, int budget) +{ + struct visornic_devdata *devdata = container_of(napi, + struct visornic_devdata, + napi); + int rx_count = 0; + + send_rcv_posts_if_needed(devdata); + service_resp_queue(devdata->cmdrsp, devdata, &rx_count); + + /* + * If there aren't any more packets to receive + * stop the poll + */ + if (rx_count < budget) + napi_complete(napi); + + return rx_count; +} + /** - * process_incoming_rsps - Checks the status of the response queue. + * poll_for_irq - Checks the status of the response queue. * @v: void pointer to the visronic devdata * * Main function of the vnic_incoming thread. Peridocially check the * response queue and drain it if needed. * Returns when thread has stopped. */ -static int -process_incoming_rsps(void *v) +static void +poll_for_irq(unsigned long v) { - struct visornic_devdata *devdata = v; - struct uiscmdrsp *cmdrsp = NULL; - const int SZ = SIZEOF_CMDRSP; + struct visornic_devdata *devdata = (struct visornic_devdata *)v; - cmdrsp = kmalloc(SZ, GFP_ATOMIC); - if (!cmdrsp) - complete_and_exit(&devdata->threadinfo.has_stopped, 0); + if (!visorchannel_signalempty( + devdata->dev->visorchannel, + IOCHAN_FROM_IOPART)) + napi_schedule(&devdata->napi); - while (1) { - wait_event_interruptible_timeout( - devdata->rsp_queue, (atomic_read( - &devdata->interrupt_rcvd) == 1), - msecs_to_jiffies(devdata->thread_wait_ms)); + atomic_set(&devdata->interrupt_rcvd, 0); - /* periodically check to see if there are any rcf bufs which - * need to get sent to the IOSP. This can only happen if - * we run out of memory when trying to allocate skbs. - */ - atomic_set(&devdata->interrupt_rcvd, 0); - send_rcv_posts_if_needed(devdata); - drain_queue(cmdrsp, devdata); - if (kthread_should_stop()) - break; - } + mod_timer(&devdata->irq_poll_timer, msecs_to_jiffies(2)); - kfree(cmdrsp); - complete_and_exit(&devdata->threadinfo.has_stopped, 0); } /** @@ -1911,12 +1830,15 @@ static int visornic_probe(struct visor_device *dev) /* set the net_xmit outstanding threshold */ /* always leave two slots open but you should have 3 at a minimum */ + /* note that max_outstanding_net_xmits must be > 0 */ devdata->max_outstanding_net_xmits = - max(3, ((devdata->num_rcv_bufs / 3) - 2)); + max_t(unsigned long, 3, ((devdata->num_rcv_bufs / 3) - 2)); devdata->upper_threshold_net_xmits = - max(2, devdata->max_outstanding_net_xmits - 1); + max_t(unsigned long, + 2, (devdata->max_outstanding_net_xmits - 1)); devdata->lower_threshold_net_xmits = - max(1, devdata->max_outstanding_net_xmits / 2); + max_t(unsigned long, + 1, (devdata->max_outstanding_net_xmits / 2)); skb_queue_head_init(&devdata->xmitbufhead); @@ -1931,8 +1853,6 @@ static int visornic_probe(struct visor_device *dev) err = -ENOMEM; goto cleanup_xmit_cmdrsp; } - INIT_WORK(&devdata->serverdown_completion, - visornic_serverdown_complete); INIT_WORK(&devdata->timeout_reset, visornic_timeout_reset); devdata->server_down = false; devdata->server_change_state = false; @@ -1950,6 +1870,17 @@ static int visornic_probe(struct visor_device *dev) /* TODO: Setup Interrupt information */ /* Let's start our threads to get responses */ + netif_napi_add(netdev, &devdata->napi, visornic_poll, 64); + + setup_timer(&devdata->irq_poll_timer, poll_for_irq, + (unsigned long)devdata); + /* + * Note: This time has to start running before the while + * loop below because the napi routine is responsible for + * setting enab_dis_acked + */ + mod_timer(&devdata->irq_poll_timer, msecs_to_jiffies(2)); + channel_offset = offsetof(struct spar_io_channel_protocol, channel_header.features); err = visorbus_read_channel(dev, channel_offset, &features, 8); @@ -1957,7 +1888,7 @@ static int visornic_probe(struct visor_device *dev) dev_err(&dev->device, "%s failed to get features from chan (%d)\n", __func__, err); - goto cleanup_xmit_cmdrsp; + goto cleanup_napi_add; } features |= ULTRA_IO_CHANNEL_IS_POLLING; @@ -1966,14 +1897,14 @@ static int visornic_probe(struct visor_device *dev) dev_err(&dev->device, "%s failed to set features in chan (%d)\n", __func__, err); - goto cleanup_xmit_cmdrsp; + goto cleanup_napi_add; } err = register_netdev(netdev); if (err) { dev_err(&dev->device, "%s register_netdev failed (%d)\n", __func__, err); - goto cleanup_xmit_cmdrsp; + goto cleanup_napi_add; } /* create debgug/sysfs directories */ @@ -1987,14 +1918,14 @@ static int visornic_probe(struct visor_device *dev) goto cleanup_xmit_cmdrsp; } - devdata->thread_wait_ms = 2; - visor_thread_start(&devdata->threadinfo, process_incoming_rsps, - devdata, "vnic_incoming"); - dev_info(&dev->device, "%s success netdev=%s\n", __func__, netdev->name); return 0; +cleanup_napi_add: + del_timer_sync(&devdata->irq_poll_timer); + netif_napi_del(&devdata->napi); + cleanup_xmit_cmdrsp: kfree(devdata->xmit_cmdrsp); @@ -2058,25 +1989,14 @@ static void visornic_remove(struct visor_device *dev) } /* going_away prevents new items being added to the workqueues */ - flush_workqueue(visornic_serverdown_workqueue); flush_workqueue(visornic_timeout_reset_workqueue); debugfs_remove_recursive(devdata->eth_debugfs_dir); unregister_netdev(netdev); /* this will call visornic_close() */ - /* this had to wait until last because visornic_close() / - * visornic_disable_with_timeout() polls waiting for state that is - * only updated by the thread - */ - if (devdata->threadinfo.id) { - visor_thread_stop(&devdata->threadinfo); - if (devdata->threadinfo.id) { - dev_err(&dev->device, "%s cannot stop worker thread\n", - __func__); - return; - } - } + del_timer_sync(&devdata->irq_poll_timer); + netif_napi_del(&devdata->napi); dev_set_drvdata(&dev->device, NULL); host_side_disappeared(devdata); @@ -2131,34 +2051,33 @@ static int visornic_resume(struct visor_device *dev, netdev = devdata->netdev; - if (devdata->server_down && !devdata->server_change_state) { - devdata->server_change_state = true; - /* Must transition channel to ATTACHED state BEFORE - * we can start using the device again. - * TODO: State transitions - */ - visor_thread_start(&devdata->threadinfo, process_incoming_rsps, - devdata, "vnic_incoming"); - init_rcv_bufs(netdev, devdata); - spin_lock_irqsave(&devdata->priv_lock, flags); - devdata->enabled = 1; - - /* Now we're ready, let's send an ENB to uisnic but until - * we get an ACK back from uisnic, we'll drop the packets - */ - devdata->enab_dis_acked = 0; + spin_lock_irqsave(&devdata->priv_lock, flags); + if (devdata->server_change_state) { spin_unlock_irqrestore(&devdata->priv_lock, flags); - - /* send enable and wait for ack - don't hold lock when - * sending enable because if the queue if sull, insert - * might sleep. - */ - send_enbdis(netdev, 1, devdata); - } else if (devdata->server_change_state) { - dev_err(&dev->device, "%s server_change_state\n", + dev_err(&dev->device, "%s server already changing state\n", __func__); - return -EIO; + return -EINVAL; } + if (!devdata->server_down) { + spin_unlock_irqrestore(&devdata->priv_lock, flags); + dev_err(&dev->device, "%s server not down\n", __func__); + complete_func(dev, 0); + return 0; + } + devdata->server_change_state = true; + spin_unlock_irqrestore(&devdata->priv_lock, flags); + + /* Must transition channel to ATTACHED state BEFORE + * we can start using the device again. + * TODO: State transitions + */ + mod_timer(&devdata->irq_poll_timer, msecs_to_jiffies(2)); + + init_rcv_bufs(netdev, devdata); + + rtnl_lock(); + dev_open(netdev); + rtnl_unlock(); complete_func(dev, 0); return 0; @@ -2189,12 +2108,6 @@ static int visornic_init(void) if (!ret) goto cleanup_debugfs; - /* create workqueue for serverdown completion */ - visornic_serverdown_workqueue = - create_singlethread_workqueue("visornic_serverdown"); - if (!visornic_serverdown_workqueue) - goto cleanup_debugfs; - /* create workqueue for tx timeout reset */ visornic_timeout_reset_workqueue = create_singlethread_workqueue("visornic_timeout_reset"); @@ -2210,8 +2123,6 @@ static int visornic_init(void) return 0; cleanup_workqueue: - flush_workqueue(visornic_serverdown_workqueue); - destroy_workqueue(visornic_serverdown_workqueue); if (visornic_timeout_reset_workqueue) { flush_workqueue(visornic_timeout_reset_workqueue); destroy_workqueue(visornic_timeout_reset_workqueue); @@ -2231,10 +2142,6 @@ static void visornic_cleanup(void) { visorbus_unregister_visor_driver(&visornic_driver); - if (visornic_serverdown_workqueue) { - flush_workqueue(visornic_serverdown_workqueue); - destroy_workqueue(visornic_serverdown_workqueue); - } if (visornic_timeout_reset_workqueue) { flush_workqueue(visornic_timeout_reset_workqueue); destroy_workqueue(visornic_timeout_reset_workqueue); diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c index b3e3c2d546a1..8e61a3b3e7e4 100644 --- a/drivers/staging/vme/devices/vme_user.c +++ b/drivers/staging/vme/devices/vme_user.c @@ -561,10 +561,8 @@ static int vme_user_probe(struct vme_dev *vdev) vme_user_cdev->ops = &vme_user_fops; vme_user_cdev->owner = THIS_MODULE; err = cdev_add(vme_user_cdev, MKDEV(VME_MAJOR, 0), VME_DEVS); - if (err) { - dev_warn(&vdev->dev, "cdev_all failed\n"); + if (err) goto err_char; - } /* Request slave resources and allocate buffers (128kB wide) */ for (i = SLAVE_MINOR; i < (SLAVE_MAX + 1); i++) { diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c index b0ea38f1911c..9e61f2df3a00 100644 --- a/drivers/staging/vt6655/baseband.c +++ b/drivers/staging/vt6655/baseband.c @@ -1728,10 +1728,8 @@ BBuGetFrameTime( unsigned int uRateIdx = (unsigned int) wRate; unsigned int uRate = 0; - if (uRateIdx > RATE_54M) { - ASSERT(0); + if (uRateIdx > RATE_54M) return 0; - } uRate = (unsigned int)awcFrameTime[uRateIdx]; @@ -1945,7 +1943,6 @@ bool BBbReadEmbedded(struct vnt_private *priv, VNSvInPortB(dwIoBase + MAC_REG_BBREGDATA, pbyData); if (ww == W_MAX_TIMEOUT) { - DBG_PORT80(0x30); pr_debug(" DBG_PORT80(0x30)\n"); return false; } @@ -1988,7 +1985,6 @@ bool BBbWriteEmbedded(struct vnt_private *priv, } if (ww == W_MAX_TIMEOUT) { - DBG_PORT80(0x31); pr_debug(" DBG_PORT80(0x31)\n"); return false; } diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index e00c0605d154..ae8fd7f491a3 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -573,17 +573,17 @@ CARDvSafeResetRx( /* init state, all RD is chip's */ for (uu = 0; uu < pDevice->sOpts.nRxDescs0; uu++) { pDesc = &(pDevice->aRD0Ring[uu]); - pDesc->m_rd0RD0.wResCount = (unsigned short)(pDevice->rx_buf_sz); + pDesc->m_rd0RD0.wResCount = cpu_to_le16(pDevice->rx_buf_sz); pDesc->m_rd0RD0.f1Owner = OWNED_BY_NIC; - pDesc->m_rd1RD1.wReqCount = (unsigned short)(pDevice->rx_buf_sz); + pDesc->m_rd1RD1.wReqCount = cpu_to_le16(pDevice->rx_buf_sz); } /* init state, all RD is chip's */ for (uu = 0; uu < pDevice->sOpts.nRxDescs1; uu++) { pDesc = &(pDevice->aRD1Ring[uu]); - pDesc->m_rd0RD0.wResCount = (unsigned short)(pDevice->rx_buf_sz); + pDesc->m_rd0RD0.wResCount = cpu_to_le16(pDevice->rx_buf_sz); pDesc->m_rd0RD0.f1Owner = OWNED_BY_NIC; - pDesc->m_rd1RD1.wReqCount = (unsigned short)(pDevice->rx_buf_sz); + pDesc->m_rd1RD1.wReqCount = cpu_to_le16(pDevice->rx_buf_sz); } /* set perPkt mode */ @@ -847,7 +847,6 @@ void CARDvSetLoopbackMode(struct vnt_private *priv, unsigned short wLoopbackMode case CARD_LB_PHY: break; default: - ASSERT(false); break; } /* set MAC loopback */ diff --git a/drivers/staging/vt6655/desc.h b/drivers/staging/vt6655/desc.h index 758eeb2afd51..c9162149eb61 100644 --- a/drivers/staging/vt6655/desc.h +++ b/drivers/staging/vt6655/desc.h @@ -170,13 +170,12 @@ typedef struct tagDEVICE_RD_INFO { struct sk_buff *skb; dma_addr_t skb_dma; - dma_addr_t curr_desc; } DEVICE_RD_INFO, *PDEVICE_RD_INFO; #ifdef __BIG_ENDIAN typedef struct tagRDES0 { - volatile unsigned short wResCount; + volatile __le16 wResCount; union { volatile u16 f15Reserved; struct { @@ -191,7 +190,7 @@ SRDES0, *PSRDES0; #else typedef struct tagRDES0 { - unsigned short wResCount; + __le16 wResCount; unsigned short f15Reserved:15; unsigned short f1Owner:1; } __attribute__ ((__packed__)) @@ -200,7 +199,7 @@ SRDES0; #endif typedef struct tagRDES1 { - unsigned short wReqCount; + __le16 wReqCount; unsigned short wReserved; } __attribute__ ((__packed__)) SRDES1; @@ -209,8 +208,8 @@ SRDES1; typedef struct tagSRxDesc { volatile SRDES0 m_rd0RD0; volatile SRDES1 m_rd1RD1; - volatile u32 buff_addr; - volatile u32 next_desc; + volatile __le32 buff_addr; + volatile __le32 next_desc; struct tagSRxDesc *next __aligned(8); volatile PDEVICE_RD_INFO pRDInfo __aligned(8); } __attribute__ ((__packed__)) @@ -246,7 +245,7 @@ STDES0; #endif typedef struct tagTDES1 { - volatile unsigned short wReqCount; + volatile __le16 wReqCount; volatile unsigned char byTCR; volatile unsigned char byReserved; } __attribute__ ((__packed__)) @@ -256,9 +255,7 @@ typedef struct tagDEVICE_TD_INFO { void *mic_hdr; struct sk_buff *skb; unsigned char *buf; - dma_addr_t skb_dma; dma_addr_t buf_dma; - dma_addr_t curr_desc; unsigned long dwReqCount; unsigned long dwHeaderLength; unsigned char byFlags; @@ -268,35 +265,14 @@ typedef struct tagDEVICE_TD_INFO { typedef struct tagSTxDesc { volatile STDES0 m_td0TD0; volatile STDES1 m_td1TD1; - volatile u32 buff_addr; - volatile u32 next_desc; + volatile __le32 buff_addr; + volatile __le32 next_desc; struct tagSTxDesc *next __aligned(8); volatile PDEVICE_TD_INFO pTDInfo __aligned(8); } __attribute__ ((__packed__)) STxDesc, *PSTxDesc; typedef const STxDesc *PCSTxDesc; -typedef struct tagSTxSyncDesc { - volatile STDES0 m_td0TD0; - volatile STDES1 m_td1TD1; - volatile u32 buff_addr; /* pointer to logical buffer */ - volatile u32 next_desc; /* pointer to next logical descriptor */ - volatile unsigned short m_wFIFOCtl; - volatile unsigned short m_wTimeStamp; - struct tagSTxSyncDesc *next __aligned(8); - volatile PDEVICE_TD_INFO pTDInfo __aligned(8); -} __attribute__ ((__packed__)) -STxSyncDesc, *PSTxSyncDesc; -typedef const STxSyncDesc *PCSTxSyncDesc; - -/* RsvTime buffer header */ -typedef struct tagSRrvTime_atim { - unsigned short wCTSTxRrvTime_ba; - unsigned short wTxRrvTime_a; -} __attribute__ ((__packed__)) -SRrvTime_atim, *PSRrvTime_atim; -typedef const SRrvTime_atim *PCSRrvTime_atim; - /* Length, Service, and Signal fields of Phy for Tx */ struct vnt_phy_field { u8 signal; @@ -310,42 +286,4 @@ union vnt_phy_field_swap { u32 field_write; }; -/* Tx FIFO header */ -typedef struct tagSTxBufHead { - u32 adwTxKey[4]; - unsigned short wFIFOCtl; - unsigned short wTimeStamp; - unsigned short wFragCtl; - unsigned char byTxPower; - unsigned char wReserved; -} __attribute__ ((__packed__)) -STxBufHead, *PSTxBufHead; -typedef const STxBufHead *PCSTxBufHead; - -typedef struct tagSBEACONCtl { - u32 BufReady:1; - u32 TSF:15; - u32 BufLen:11; - u32 Reserved:5; -} __attribute__ ((__packed__)) -SBEACONCtl; - -typedef struct tagSSecretKey { - u32 dwLowDword; - unsigned char byHighByte; -} __attribute__ ((__packed__)) -SSecretKey; - -typedef struct tagSKeyEntry { - unsigned char abyAddrHi[2]; - unsigned short wKCTL; - unsigned char abyAddrLo[4]; - u32 dwKey0[4]; - u32 dwKey1[4]; - u32 dwKey2[4]; - u32 dwKey3[4]; - u32 dwKey4[4]; -} __attribute__ ((__packed__)) -SKeyEntry; - #endif /* __DESC_H__ */ diff --git a/drivers/staging/vt6655/device_cfg.h b/drivers/staging/vt6655/device_cfg.h index a4a8a8489e0b..b4c9547d3138 100644 --- a/drivers/staging/vt6655/device_cfg.h +++ b/drivers/staging/vt6655/device_cfg.h @@ -69,19 +69,4 @@ typedef enum _chip_type { VT3253 = 1 } CHIP_TYPE, *PCHIP_TYPE; -#ifdef VIAWET_DEBUG -#define ASSERT(x) \ -do { \ - if (!(x)) { \ - pr_err("assertion %s failed: file %s line %d\n", \ - #x, __func__, __LINE__); \ - *(int *)0 = 0; \ - } \ -} while (0) -#define DBG_PORT80(value) outb(value, 0x80) -#else -#define ASSERT(x) -#define DBG_PORT80(value) -#endif - #endif diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index f7d70427d050..b74af8d89fe6 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -623,12 +623,11 @@ static void device_init_rd0_ring(struct vnt_private *pDevice) for (i = 0; i < pDevice->sOpts.nRxDescs0; i ++, curr += sizeof(SRxDesc)) { pDesc = &(pDevice->aRD0Ring[i]); pDesc->pRDInfo = alloc_rd_info(); - ASSERT(pDesc->pRDInfo); + if (!device_alloc_rx_buf(pDevice, pDesc)) dev_err(&pDevice->pcid->dev, "can not alloc rx bufs\n"); pDesc->next = &(pDevice->aRD0Ring[(i+1) % pDevice->sOpts.nRxDescs0]); - pDesc->pRDInfo->curr_desc = cpu_to_le32(curr); pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc)); } @@ -647,12 +646,11 @@ static void device_init_rd1_ring(struct vnt_private *pDevice) for (i = 0; i < pDevice->sOpts.nRxDescs1; i ++, curr += sizeof(SRxDesc)) { pDesc = &(pDevice->aRD1Ring[i]); pDesc->pRDInfo = alloc_rd_info(); - ASSERT(pDesc->pRDInfo); + if (!device_alloc_rx_buf(pDevice, pDesc)) dev_err(&pDevice->pcid->dev, "can not alloc rx bufs\n"); pDesc->next = &(pDevice->aRD1Ring[(i+1) % pDevice->sOpts.nRxDescs1]); - pDesc->pRDInfo->curr_desc = cpu_to_le32(curr); pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc)); } @@ -705,13 +703,12 @@ static void device_init_td0_ring(struct vnt_private *pDevice) for (i = 0; i < pDevice->sOpts.nTxDescs[0]; i++, curr += sizeof(STxDesc)) { pDesc = &(pDevice->apTD0Rings[i]); pDesc->pTDInfo = alloc_td_info(); - ASSERT(pDesc->pTDInfo); + if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) { pDesc->pTDInfo->buf = pDevice->tx0_bufs + (i)*PKT_BUF_SZ; pDesc->pTDInfo->buf_dma = pDevice->tx_bufs_dma0 + (i)*PKT_BUF_SZ; } pDesc->next = &(pDevice->apTD0Rings[(i+1) % pDevice->sOpts.nTxDescs[0]]); - pDesc->pTDInfo->curr_desc = cpu_to_le32(curr); pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc)); } @@ -731,13 +728,12 @@ static void device_init_td1_ring(struct vnt_private *pDevice) for (i = 0; i < pDevice->sOpts.nTxDescs[1]; i++, curr += sizeof(STxDesc)) { pDesc = &(pDevice->apTD1Rings[i]); pDesc->pTDInfo = alloc_td_info(); - ASSERT(pDesc->pTDInfo); + if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) { pDesc->pTDInfo->buf = pDevice->tx1_bufs + (i) * PKT_BUF_SZ; pDesc->pTDInfo->buf_dma = pDevice->tx_bufs_dma1 + (i) * PKT_BUF_SZ; } pDesc->next = &(pDevice->apTD1Rings[(i + 1) % pDevice->sOpts.nTxDescs[1]]); - pDesc->pTDInfo->curr_desc = cpu_to_le32(curr); pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc)); } @@ -754,10 +750,6 @@ static void device_free_td0_ring(struct vnt_private *pDevice) PSTxDesc pDesc = &(pDevice->apTD0Rings[i]); PDEVICE_TD_INFO pTDInfo = pDesc->pTDInfo; - if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma)) - dma_unmap_single(&pDevice->pcid->dev, pTDInfo->skb_dma, - pTDInfo->skb->len, DMA_TO_DEVICE); - dev_kfree_skb(pTDInfo->skb); kfree(pDesc->pTDInfo); } @@ -771,10 +763,6 @@ static void device_free_td1_ring(struct vnt_private *pDevice) PSTxDesc pDesc = &(pDevice->apTD1Rings[i]); PDEVICE_TD_INFO pTDInfo = pDesc->pTDInfo; - if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma)) - dma_unmap_single(&pDevice->pcid->dev, pTDInfo->skb_dma, - pTDInfo->skb->len, DMA_TO_DEVICE); - dev_kfree_skb(pTDInfo->skb); kfree(pDesc->pTDInfo); } @@ -818,7 +806,6 @@ static bool device_alloc_rx_buf(struct vnt_private *pDevice, PSRxDesc pRD) pRDInfo->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); if (pRDInfo->skb == NULL) return false; - ASSERT(pRDInfo->skb); pRDInfo->skb_dma = dma_map_single(&pDevice->pcid->dev, @@ -976,16 +963,9 @@ static void device_free_tx_buf(struct vnt_private *pDevice, PSTxDesc pDesc) PDEVICE_TD_INFO pTDInfo = pDesc->pTDInfo; struct sk_buff *skb = pTDInfo->skb; - /* pre-allocated buf_dma can't be unmapped. */ - if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma)) { - dma_unmap_single(&pDevice->pcid->dev, pTDInfo->skb_dma, - skb->len, DMA_TO_DEVICE); - } - if (skb) ieee80211_tx_status_irqsafe(pDevice->hw, skb); - pTDInfo->skb_dma = 0; pTDInfo->skb = NULL; pTDInfo->byFlags = 0; } @@ -1216,7 +1196,7 @@ static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb) head_td->m_td1TD1.wReqCount = cpu_to_le16((u16)head_td->pTDInfo->dwReqCount); - head_td->buff_addr = cpu_to_le32(head_td->pTDInfo->skb_dma); + head_td->buff_addr = cpu_to_le32(head_td->pTDInfo->buf_dma); /* Poll Transmit the adapter */ wmb(); @@ -1411,7 +1391,7 @@ static void vnt_bss_info_changed(struct ieee80211_hw *hw, priv->current_aid = conf->aid; - if (changed & BSS_CHANGED_BSSID) { + if (changed & BSS_CHANGED_BSSID && conf->bssid) { unsigned long flags; spin_lock_irqsave(&priv->lock, flags); @@ -1476,8 +1456,9 @@ static void vnt_bss_info_changed(struct ieee80211_hw *hw, } } - if (changed & BSS_CHANGED_ASSOC && priv->op_mode != NL80211_IFTYPE_AP) { - if (conf->assoc) { + if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BEACON_INFO) && + priv->op_mode != NL80211_IFTYPE_AP) { + if (conf->assoc && conf->beacon_rate) { CARDbUpdateTSF(priv, conf->beacon_rate->hw_value, conf->sync_tsf); @@ -1767,6 +1748,12 @@ vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent) return -ENODEV; } + if (dma_set_mask(&pcid->dev, DMA_BIT_MASK(32))) { + dev_err(&pcid->dev, ": Failed to set dma 32 bit mask\n"); + device_free_info(priv); + return -ENODEV; + } + INIT_WORK(&priv->interrupt_work, vnt_interrupt_work); /* do reset */ diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c index b25ee962558d..e14eed160a19 100644 --- a/drivers/staging/vt6655/dpc.c +++ b/drivers/staging/vt6655/dpc.c @@ -144,7 +144,7 @@ bool vnt_receive_frame(struct vnt_private *priv, PSRxDesc curr_rd) priv->rx_buf_sz, DMA_FROM_DEVICE); frame_size = le16_to_cpu(curr_rd->m_rd1RD1.wReqCount) - - cpu_to_le16(curr_rd->m_rd0RD0.wResCount); + - le16_to_cpu(curr_rd->m_rd0RD0.wResCount); if ((frame_size > 2364) || (frame_size < 33)) { /* Frame Size error drop this packet.*/ diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c index aed530f022b8..3dfd333475c0 100644 --- a/drivers/staging/vt6655/mac.c +++ b/drivers/staging/vt6655/mac.c @@ -186,7 +186,6 @@ void MACvSetLoopbackMode(void __iomem *dwIoBase, unsigned char byLoopbackMode) { unsigned char byOrgValue; - ASSERT(byLoopbackMode < 3); byLoopbackMode <<= 6; /* set TCR */ VNSvInPortB(dwIoBase + MAC_REG_TEST, &byOrgValue); @@ -374,7 +373,6 @@ bool MACbSafeRxOff(void __iomem *dwIoBase) break; } if (ww == W_MAX_TIMEOUT) { - DBG_PORT80(0x10); pr_debug(" DBG_PORT80(0x10)\n"); return false; } @@ -384,7 +382,6 @@ bool MACbSafeRxOff(void __iomem *dwIoBase) break; } if (ww == W_MAX_TIMEOUT) { - DBG_PORT80(0x11); pr_debug(" DBG_PORT80(0x11)\n"); return false; } @@ -398,7 +395,6 @@ bool MACbSafeRxOff(void __iomem *dwIoBase) break; } if (ww == W_MAX_TIMEOUT) { - DBG_PORT80(0x12); pr_debug(" DBG_PORT80(0x12)\n"); return false; } @@ -436,7 +432,6 @@ bool MACbSafeTxOff(void __iomem *dwIoBase) break; } if (ww == W_MAX_TIMEOUT) { - DBG_PORT80(0x20); pr_debug(" DBG_PORT80(0x20)\n"); return false; } @@ -446,7 +441,6 @@ bool MACbSafeTxOff(void __iomem *dwIoBase) break; } if (ww == W_MAX_TIMEOUT) { - DBG_PORT80(0x21); pr_debug(" DBG_PORT80(0x21)\n"); return false; } @@ -461,7 +455,6 @@ bool MACbSafeTxOff(void __iomem *dwIoBase) break; } if (ww == W_MAX_TIMEOUT) { - DBG_PORT80(0x24); pr_debug(" DBG_PORT80(0x24)\n"); return false; } @@ -486,13 +479,11 @@ bool MACbSafeStop(void __iomem *dwIoBase) MACvRegBitsOff(dwIoBase, MAC_REG_TCR, TCR_AUTOBCNTX); if (!MACbSafeRxOff(dwIoBase)) { - DBG_PORT80(0xA1); pr_debug(" MACbSafeRxOff == false)\n"); MACbSafeSoftwareReset(dwIoBase); return false; } if (!MACbSafeTxOff(dwIoBase)) { - DBG_PORT80(0xA2); pr_debug(" MACbSafeTxOff == false)\n"); MACbSafeSoftwareReset(dwIoBase); return false; @@ -590,9 +581,6 @@ void MACvSetCurrRx0DescAddr(void __iomem *dwIoBase, unsigned long dwCurrDescAddr break; } - if (ww == W_MAX_TIMEOUT) - DBG_PORT80(0x13); - VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR0, dwCurrDescAddr); if (byOrgDMACtl & DMACTL_RUN) VNSvOutPortB(dwIoBase + MAC_REG_RXDMACTL0, DMACTL_RUN); @@ -627,8 +615,6 @@ void MACvSetCurrRx1DescAddr(void __iomem *dwIoBase, unsigned long dwCurrDescAddr if (!(byData & DMACTL_RUN)) break; } - if (ww == W_MAX_TIMEOUT) - DBG_PORT80(0x14); VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR1, dwCurrDescAddr); if (byOrgDMACtl & DMACTL_RUN) @@ -666,8 +652,6 @@ void MACvSetCurrTx0DescAddrEx(void __iomem *dwIoBase, if (!(byData & DMACTL_RUN)) break; } - if (ww == W_MAX_TIMEOUT) - DBG_PORT80(0x25); VNSvOutPortD(dwIoBase + MAC_REG_TXDMAPTR0, dwCurrDescAddr); if (byOrgDMACtl & DMACTL_RUN) @@ -706,7 +690,6 @@ void MACvSetCurrAC0DescAddrEx(void __iomem *dwIoBase, break; } if (ww == W_MAX_TIMEOUT) { - DBG_PORT80(0x26); pr_debug(" DBG_PORT80(0x26)\n"); } VNSvOutPortD(dwIoBase + MAC_REG_AC0DMAPTR, dwCurrDescAddr); @@ -807,7 +790,6 @@ bool MACbPSWakeup(void __iomem *dwIoBase) break; } if (ww == W_MAX_TIMEOUT) { - DBG_PORT80(0x36); pr_debug(" DBG_PORT80(0x33)\n"); return false; } diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index 534338c46619..380b879c05db 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -387,7 +387,6 @@ s_uGetDataDuration( break; } - ASSERT(false); return 0; } @@ -1089,7 +1088,7 @@ s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType, /* Set RrvTime/RTS/CTS Buffer */ - wTxBufSize = sizeof(STxBufHead); + wTxBufSize = sizeof(struct vnt_tx_fifo_head); if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {/* 802.11g packet */ if (byFBOption == AUTO_FB_NONE) { @@ -1203,7 +1202,6 @@ s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType, ptdCurr->pTDInfo->dwReqCount = cbReqCount; ptdCurr->pTDInfo->dwHeaderLength = cbHeaderLength; - ptdCurr->pTDInfo->skb_dma = ptdCurr->pTDInfo->buf_dma; return cbHeaderLength; } diff --git a/drivers/staging/vt6655/rxtx.h b/drivers/staging/vt6655/rxtx.h index b9bd1639b13e..54694df14e44 100644 --- a/drivers/staging/vt6655/rxtx.h +++ b/drivers/staging/vt6655/rxtx.h @@ -197,4 +197,4 @@ int vnt_beacon_make(struct vnt_private *, struct ieee80211_vif *); int vnt_beacon_enable(struct vnt_private *, struct ieee80211_vif *, struct ieee80211_bss_conf *); -#endif // __RXTX_H__ +#endif /* __RXTX_H__ */ diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index f97323f19acf..af572d718135 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -701,7 +701,7 @@ static void vnt_bss_info_changed(struct ieee80211_hw *hw, priv->current_aid = conf->aid; - if (changed & BSS_CHANGED_BSSID) + if (changed & BSS_CHANGED_BSSID && conf->bssid) vnt_mac_set_bssid_addr(priv, (u8 *)conf->bssid); diff --git a/drivers/staging/wilc1000/Kconfig b/drivers/staging/wilc1000/Kconfig index 062d9c5ca4bd..51bbf468fe45 100644 --- a/drivers/staging/wilc1000/Kconfig +++ b/drivers/staging/wilc1000/Kconfig @@ -37,17 +37,26 @@ choice bool "SDIO support" depends on MMC ---help--- - This module adds support for the SDIO interface - of adapters using WILC chipset. Select this if - your platform is using the SDIO bus. + This module adds support for the SDIO interface of adapters using + WILC1000 chipset. The Atmel WILC1000 SDIO is a full speed interface. + It meets SDIO card specification version 2.0. The interface supports + the 1-bit/4-bit SD transfer mode at the clock range of 0-50 MHz. + The host can use this interface to read and write from any register + within the chip as well as configure the WILC1000 for data DMA. + To use this interface, pin9 (SDIO_SPI_CFG) must be grounded. Select + this if your platform is using the SDIO bus. config WILC1000_SPI depends on SPI bool "SPI support" ---help--- - This module adds support for the SPI interface - of adapters using WILC chipset. Select this if - your platform is using the SPI bus. + This module adds support for the SPI interface of adapters using + WILC1000 chipset. The Atmel WILC1000 has a Serial Peripheral + Interface (SPI) that operates as a SPI slave. This SPI interface can + be used for control and for serial I/O of 802.11 data. The SPI is a + full-duplex slave synchronous serial interface that is available + immediately following reset when pin 9 (SDIO_SPI_CFG) is tied to + VDDIO. Select this if your platform is using the SPI bus. endchoice config WILC1000_HW_OOB_INTR @@ -55,5 +64,8 @@ config WILC1000_HW_OOB_INTR depends on WILC1000 && WILC1000_SDIO default n ---help--- - If your platform don't recognize SDIO IRQ, connect chipset external IRQ pin - and check this option. Or, Use this to get all interrupts including SDIO interrupts. + This option enables out-of-band interrupt support for the WILC1000 + chipset. This OOB interrupt is intended to provide a faster interrupt + mechanism for SDIO host controllers that don't support SDIO interrupt. + Select this option If the SDIO host controller in your platform + doesn't support SDIO time devision interrupt. diff --git a/drivers/staging/wilc1000/Makefile b/drivers/staging/wilc1000/Makefile index a78c4d529a58..5ca8fa253306 100644 --- a/drivers/staging/wilc1000/Makefile +++ b/drivers/staging/wilc1000/Makefile @@ -25,10 +25,10 @@ ccflags-$(CONFIG_WILC1000_PREALLOCATE_AT_LOADING_DRIVER) += -DMEMORY_STATIC \ ccflags-$(CONFIG_WILC1000_DYNAMICALLY_ALLOCATE_MEMROY) += -DWILC_NORMAL_ALLOC -wilc1000-objs := wilc_wfi_netdevice.o wilc_wfi_cfgoperations.o linux_wlan.o linux_mon.o \ +wilc1000-objs := wilc_wfi_cfgoperations.o linux_wlan.o linux_mon.o \ wilc_memory.o wilc_msgqueue.o wilc_sleep.o wilc_strutils.o \ wilc_timer.o coreconfigurator.o host_interface.o \ - fifo_buffer.o wilc_sdio.o wilc_spi.o wilc_wlan_cfg.o wilc_debugfs.o + wilc_sdio.o wilc_spi.o wilc_wlan_cfg.o wilc_debugfs.o wilc1000-$(CONFIG_WILC1000_SDIO) += linux_wlan_sdio.o wilc1000-$(CONFIG_WILC1000_SPI) += linux_wlan_spi.o diff --git a/drivers/staging/wilc1000/coreconfigsimulator.h b/drivers/staging/wilc1000/coreconfigsimulator.h deleted file mode 100644 index 5e01f8e4a41d..000000000000 --- a/drivers/staging/wilc1000/coreconfigsimulator.h +++ /dev/null @@ -1,17 +0,0 @@ - -/*! - * @file coreconfigsimulator.h - * @brief - * @author - * @sa coreconfigsimulator.c - * @date 1 Mar 2012 - * @version 1.0 - */ - -#ifndef CORECONFIGSIMULATOR_H -#define CORECONFIGSIMULATOR_H - -extern s32 CoreConfigSimulatorInit(void); -extern s32 CoreConfigSimulatorDeInit(void); - -#endif diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index b0696141e10f..72ff7d42377e 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -681,9 +681,9 @@ s32 CoreConfiguratorInit(void) goto _fail_; } - WILC_memset((void *)gps8ConfigPacket, 0, MAX_PACKET_BUFF_SIZE); + memset((void *)gps8ConfigPacket, 0, MAX_PACKET_BUFF_SIZE); - WILC_memset((void *)(&gstrConfigPktInfo), 0, sizeof(tstrConfigPktInfo)); + memset((void *)(&gstrConfigPktInfo), 0, sizeof(tstrConfigPktInfo)); _fail_: return s32Error; } @@ -706,11 +706,10 @@ u8 *get_tim_elm(u8 *pu8msa, u16 u16RxLen, u16 u16TagParamOffset) /* Search for the TIM Element Field and return if the element is found */ while (u16index < (u16RxLen - FCS_LEN)) { - if (pu8msa[u16index] == ITIM) { + if (pu8msa[u16index] == ITIM) return &pu8msa[u16index]; - } else { + else u16index += (IE_HDR_LEN + pu8msa[u16index + 1]); - } } return 0; @@ -812,7 +811,7 @@ s32 ParseNetworkInfo(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo) u32 u32Tsf_Hi; pstrNetworkInfo = (tstrNetworkInfo *)WILC_MALLOC(sizeof(tstrNetworkInfo)); - WILC_memset((void *)(pstrNetworkInfo), 0, sizeof(tstrNetworkInfo)); + memset((void *)(pstrNetworkInfo), 0, sizeof(tstrNetworkInfo)); pstrNetworkInfo->s8rssi = pu8WidVal[0]; @@ -855,15 +854,14 @@ s32 ParseNetworkInfo(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo) /* Get DTIM Period */ pu8TimElm = get_tim_elm(pu8msa, (u16RxLen + FCS_LEN), u8index); - if (pu8TimElm != 0) { + if (pu8TimElm != 0) pstrNetworkInfo->u8DtimPeriod = pu8TimElm[3]; - } pu8IEs = &pu8msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN]; u16IEsLen = u16RxLen - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN); if (u16IEsLen > 0) { pstrNetworkInfo->pu8IEs = (u8 *)WILC_MALLOC(u16IEsLen); - WILC_memset((void *)(pstrNetworkInfo->pu8IEs), 0, u16IEsLen); + memset((void *)(pstrNetworkInfo->pu8IEs), 0, u16IEsLen); WILC_memcpy(pstrNetworkInfo->pu8IEs, pu8IEs, u16IEsLen); } @@ -930,7 +928,7 @@ s32 ParseAssocRespInfo(u8 *pu8Buffer, u32 u32BufferLen, u16 u16IEsLen = 0; pstrConnectRespInfo = (tstrConnectRespInfo *)WILC_MALLOC(sizeof(tstrConnectRespInfo)); - WILC_memset((void *)(pstrConnectRespInfo), 0, sizeof(tstrConnectRespInfo)); + memset((void *)(pstrConnectRespInfo), 0, sizeof(tstrConnectRespInfo)); /* u16AssocRespLen = pu8Buffer[0]; */ u16AssocRespLen = (u16)u32BufferLen; @@ -950,7 +948,7 @@ s32 ParseAssocRespInfo(u8 *pu8Buffer, u32 u32BufferLen, u16IEsLen = u16AssocRespLen - (CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN); pstrConnectRespInfo->pu8RespIEs = (u8 *)WILC_MALLOC(u16IEsLen); - WILC_memset((void *)(pstrConnectRespInfo->pu8RespIEs), 0, u16IEsLen); + memset((void *)(pstrConnectRespInfo->pu8RespIEs), 0, u16IEsLen); WILC_memcpy(pstrConnectRespInfo->pu8RespIEs, pu8IEs, u16IEsLen); pstrConnectRespInfo->u16RespIEsLen = u16IEsLen; @@ -1024,7 +1022,7 @@ s32 ParseSurveyResults(u8 ppu8RcvdSiteSurveyResults[][MAX_SURVEY_RESULT_FRAG_SIZ WILC_ERRORREPORT(s32Error, WILC_NO_MEM); } - WILC_memset((void *)(pstrSurveyResults), 0, u32SurveyResultsCount * sizeof(wid_site_survey_reslts_s)); + memset((void *)(pstrSurveyResults), 0, u32SurveyResultsCount * sizeof(wid_site_survey_reslts_s)); u32SurveyResultsCount = 0; @@ -1528,11 +1526,10 @@ s32 further_process_response(u8 *resp, u8 cfg_str[256] = {0}; tenuWIDtype enuWIDtype = WID_UNDEF; - if (process_wid_num) { + if (process_wid_num) enuWIDtype = get_wid_type(g_wid_num); - } else { + else enuWIDtype = gastrWIDs[cnt].enuWIDtype; - } switch (enuWIDtype) { @@ -1872,94 +1869,11 @@ s32 ConfigWaitResponse(char *pcRespBuffer, s32 s32MaxRespBuffLen, s32 *ps32Bytes *ps32BytesRead = gstrConfigPktInfo.s32BytesRead; } - WILC_memset((void *)(&gstrConfigPktInfo), 0, sizeof(tstrConfigPktInfo)); + memset((void *)(&gstrConfigPktInfo), 0, sizeof(tstrConfigPktInfo)); return s32Error; } -/** - * @brief sends certain Configuration Packet based on the input WIDs pstrWIDs - * and retrieves the packet response pu8RxResp - * @details - * @param[in] pstrWIDs WIDs to be sent in the configuration packet - * @param[in] u32WIDsCount number of WIDs to be sent in the configuration packet - * @param[out] pu8RxResp The received Packet Response - * @param[out] ps32RxRespLen Length of the received Packet Response - * @return Error code indicating success/failure - * @note - * @author mabubakr - * @date 1 Mar 2012 - * @version 1.0 - */ -#ifdef SIMULATION -s32 SendConfigPkt(u8 u8Mode, tstrWID *pstrWIDs, - u32 u32WIDsCount, bool bRespRequired, u32 drvHandler) -{ - s32 s32Error = WILC_SUCCESS; - s32 err = WILC_SUCCESS; - s32 s32ConfigPacketLen = 0; - s32 s32RcvdRespLen = 0; - - down(&SemHandleSendPkt); - - /*set the packet mode*/ - g_oper_mode = u8Mode; - - WILC_memset((void *)gps8ConfigPacket, 0, MAX_PACKET_BUFF_SIZE); - - if (CreateConfigPacket(gps8ConfigPacket, &s32ConfigPacketLen, pstrWIDs, u32WIDsCount) != WILC_SUCCESS) { - s32Error = WILC_FAIL; - goto End_ConfigPkt; - } - /*bug 3878*/ - gstrConfigPktInfo.pcRespBuffer = gps8ConfigPacket; - gstrConfigPktInfo.s32MaxRespBuffLen = MAX_PACKET_BUFF_SIZE; - PRINT_INFO(CORECONFIG_DBG, "GLOBAL =bRespRequired =%d\n", bRespRequired); - gstrConfigPktInfo.bRespRequired = bRespRequired; - - s32Error = SendRawPacket(gps8ConfigPacket, s32ConfigPacketLen); - if (s32Error != WILC_SUCCESS) { - goto End_ConfigPkt; - } - - WILC_memset((void *)gps8ConfigPacket, 0, MAX_PACKET_BUFF_SIZE); - - ConfigWaitResponse(gps8ConfigPacket, MAX_PACKET_BUFF_SIZE, &s32RcvdRespLen, bRespRequired); - - - if (bRespRequired) { - /* If the operating Mode is GET, then we expect a response frame from */ - /* the driver. Hence start listening to the port for response */ - if (g_oper_mode == GET_CFG) { - #if 1 - err = ParseResponse(gps8ConfigPacket, pstrWIDs); - if (err != 0) { - s32Error = WILC_FAIL; - goto End_ConfigPkt; - } else { - s32Error = WILC_SUCCESS; - } - #endif - } else { - err = ParseWriteResponse(gps8ConfigPacket); - if (err != WRITE_RESP_SUCCESS) { - s32Error = WILC_FAIL; - goto End_ConfigPkt; - } else { - s32Error = WILC_SUCCESS; - } - } - - - } - - -End_ConfigPkt: - up(&SemHandleSendPkt); - - return s32Error; -} -#endif s32 ConfigProvideResponse(char *pcRespBuffer, s32 s32RespLen) { s32 s32Error = WILC_SUCCESS; @@ -2052,8 +1966,6 @@ s32 CoreConfiguratorDeInit(void) return s32Error; } - -#ifndef SIMULATION /*Using the global handle of the driver*/ extern wilc_wlan_oup_t *gpstrWlanOps; /** @@ -2127,4 +2039,3 @@ s32 SendConfigPkt(u8 u8Mode, tstrWID *pstrWIDs, return ret; } -#endif diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 9059c8df7ce5..56ff2ba139ed 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -8,7 +8,6 @@ * @version 1.0 */ - #ifndef CORECONFIGURATOR_H #define CORECONFIGURATOR_H @@ -42,7 +41,6 @@ extern u16 g_num_total_switches; #define AID_LEN 2 #define IE_HDR_LEN 2 - /* Operating Mode: SET */ #define SET_CFG 0 /* Operating Mode: GET */ @@ -59,15 +57,12 @@ extern u16 g_num_total_switches; #define MAC_CONNECTED 1 #define MAC_DISCONNECTED 0 - - /*****************************************************************************/ /* Function Macros */ /*****************************************************************************/ #define MAKE_WORD16(lsb, msb) ((((u16)(msb) << 8) & 0xFF00) | (lsb)) #define MAKE_WORD32(lsw, msw) ((((u32)(msw) << 16) & 0xFFFF0000) | (lsw)) - /*****************************************************************************/ /* Type Definitions */ /*****************************************************************************/ @@ -140,7 +135,6 @@ typedef struct { u16 u16RespIEsLen; } tstrConnectRespInfo; - typedef struct { u8 au8bssid[6]; u8 *pu8ReqIEs; @@ -150,8 +144,6 @@ typedef struct { u16 u16ConnectStatus; } tstrConnectInfo; - - typedef struct { u16 u16reason; u8 *ie; @@ -175,17 +167,18 @@ extern s32 CoreConfiguratorInit(void); extern s32 CoreConfiguratorDeInit(void); extern s32 SendConfigPkt(u8 u8Mode, tstrWID *pstrWIDs, - u32 u32WIDsCount, bool bRespRequired, u32 drvHandler); + u32 u32WIDsCount, bool bRespRequired, u32 drvHandler); extern s32 ParseNetworkInfo(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo); extern s32 DeallocateNetworkInfo(tstrNetworkInfo *pstrNetworkInfo); extern s32 ParseAssocRespInfo(u8 *pu8Buffer, u32 u32BufferLen, - tstrConnectRespInfo **ppstrConnectRespInfo); + tstrConnectRespInfo **ppstrConnectRespInfo); extern s32 DeallocateAssocRespInfo(tstrConnectRespInfo *pstrConnectRespInfo); #ifndef CONNECT_DIRECT extern s32 ParseSurveyResults(u8 ppu8RcvdSiteSurveyResults[][MAX_SURVEY_RESULT_FRAG_SIZE], - wid_site_survey_reslts_s **ppstrSurveyResults, u32 *pu32SurveyResultsCount); + wid_site_survey_reslts_s **ppstrSurveyResults, + u32 *pu32SurveyResultsCount); extern s32 DeallocateSurveyResults(wid_site_survey_reslts_s *pstrSurveyResults); #endif diff --git a/drivers/staging/wilc1000/fifo_buffer.c b/drivers/staging/wilc1000/fifo_buffer.c deleted file mode 100644 index 86eb82e36be0..000000000000 --- a/drivers/staging/wilc1000/fifo_buffer.c +++ /dev/null @@ -1,132 +0,0 @@ - - -#include "fifo_buffer.h" - - - -u32 FIFO_InitBuffer(tHANDLE *hBuffer, u32 u32BufferLength) -{ - u32 u32Error = 0; - tstrFifoHandler *pstrFifoHandler = WILC_MALLOC (sizeof (tstrFifoHandler)); - if (pstrFifoHandler) { - WILC_memset (pstrFifoHandler, 0, sizeof (tstrFifoHandler)); - pstrFifoHandler->pu8Buffer = WILC_MALLOC (u32BufferLength); - if (pstrFifoHandler->pu8Buffer) { - pstrFifoHandler->u32BufferLength = u32BufferLength; - WILC_memset (pstrFifoHandler->pu8Buffer, 0, u32BufferLength); - /* create semaphore */ - sema_init(&pstrFifoHandler->SemBuffer, 1); - *hBuffer = pstrFifoHandler; - } else { - *hBuffer = NULL; - u32Error = 1; - } - } else { - u32Error = 1; - } - return u32Error; -} -u32 FIFO_DeInit(tHANDLE hFifo) -{ - u32 u32Error = 0; - tstrFifoHandler *pstrFifoHandler = (tstrFifoHandler *) hFifo; - if (pstrFifoHandler) { - if (pstrFifoHandler->pu8Buffer) - WILC_FREE (pstrFifoHandler->pu8Buffer); - else - u32Error = 1; - - WILC_FREE (pstrFifoHandler); - } else { - u32Error = 1; - } - return u32Error; -} - -u32 FIFO_ReadBytes(tHANDLE hFifo, u8 *pu8Buffer, u32 u32BytesToRead, u32 *pu32BytesRead) -{ - u32 u32Error = 0; - tstrFifoHandler *pstrFifoHandler = (tstrFifoHandler *) hFifo; - if (pstrFifoHandler && pu32BytesRead) { - if (pstrFifoHandler->u32TotalBytes) { - down(&pstrFifoHandler->SemBuffer); - - if (u32BytesToRead > pstrFifoHandler->u32TotalBytes) - *pu32BytesRead = pstrFifoHandler->u32TotalBytes; - else - *pu32BytesRead = u32BytesToRead; - - if ((pstrFifoHandler->u32ReadOffset + u32BytesToRead) <= pstrFifoHandler->u32BufferLength) { - WILC_memcpy(pu8Buffer, pstrFifoHandler->pu8Buffer + pstrFifoHandler->u32ReadOffset, - *pu32BytesRead); - /* update read offset and total bytes */ - pstrFifoHandler->u32ReadOffset += u32BytesToRead; - pstrFifoHandler->u32TotalBytes -= u32BytesToRead; - - } else { - u32 u32FirstPart = - pstrFifoHandler->u32BufferLength - pstrFifoHandler->u32ReadOffset; - WILC_memcpy(pu8Buffer, pstrFifoHandler->pu8Buffer + pstrFifoHandler->u32ReadOffset, - u32FirstPart); - WILC_memcpy(pu8Buffer + u32FirstPart, pstrFifoHandler->pu8Buffer, - u32BytesToRead - u32FirstPart); - /* update read offset and total bytes */ - pstrFifoHandler->u32ReadOffset = u32BytesToRead - u32FirstPart; - pstrFifoHandler->u32TotalBytes -= u32BytesToRead; - } - up(&pstrFifoHandler->SemBuffer); - } else { - u32Error = 1; - } - } else { - u32Error = 1; - } - return u32Error; -} - -u32 FIFO_WriteBytes(tHANDLE hFifo, u8 *pu8Buffer, u32 u32BytesToWrite, bool bForceOverWrite) -{ - u32 u32Error = 0; - tstrFifoHandler *pstrFifoHandler = (tstrFifoHandler *) hFifo; - if (pstrFifoHandler) { - if (u32BytesToWrite < pstrFifoHandler->u32BufferLength) { - if ((pstrFifoHandler->u32TotalBytes + u32BytesToWrite) <= pstrFifoHandler->u32BufferLength || - bForceOverWrite) { - down(&pstrFifoHandler->SemBuffer); - if ((pstrFifoHandler->u32WriteOffset + u32BytesToWrite) <= pstrFifoHandler->u32BufferLength) { - WILC_memcpy(pstrFifoHandler->pu8Buffer + pstrFifoHandler->u32WriteOffset, pu8Buffer, - u32BytesToWrite); - /* update read offset and total bytes */ - pstrFifoHandler->u32WriteOffset += u32BytesToWrite; - pstrFifoHandler->u32TotalBytes += u32BytesToWrite; - - } else { - u32 u32FirstPart = - pstrFifoHandler->u32BufferLength - pstrFifoHandler->u32WriteOffset; - WILC_memcpy(pstrFifoHandler->pu8Buffer + pstrFifoHandler->u32WriteOffset, pu8Buffer, - u32FirstPart); - WILC_memcpy(pstrFifoHandler->pu8Buffer, pu8Buffer + u32FirstPart, - u32BytesToWrite - u32FirstPart); - /* update read offset and total bytes */ - pstrFifoHandler->u32WriteOffset = u32BytesToWrite - u32FirstPart; - pstrFifoHandler->u32TotalBytes += u32BytesToWrite; - } - /* if data overwriten */ - if (pstrFifoHandler->u32TotalBytes > pstrFifoHandler->u32BufferLength) { - /* adjust read offset to the oldest data available */ - pstrFifoHandler->u32ReadOffset = pstrFifoHandler->u32WriteOffset; - /* data availabe is the buffer length */ - pstrFifoHandler->u32TotalBytes = pstrFifoHandler->u32BufferLength; - } - up(&pstrFifoHandler->SemBuffer); - } else { - u32Error = 1; - } - } else { - u32Error = 1; - } - } else { - u32Error = 1; - } - return u32Error; -} diff --git a/drivers/staging/wilc1000/fifo_buffer.h b/drivers/staging/wilc1000/fifo_buffer.h deleted file mode 100644 index 7b76998e4238..000000000000 --- a/drivers/staging/wilc1000/fifo_buffer.h +++ /dev/null @@ -1,26 +0,0 @@ - -#include <linux/types.h> -#include <linux/semaphore.h> -#include "wilc_memory.h" -#include "wilc_strutils.h" - - -#define tHANDLE void * - -typedef struct { - u8 *pu8Buffer; - u32 u32BufferLength; - u32 u32WriteOffset; - u32 u32ReadOffset; - u32 u32TotalBytes; - struct semaphore SemBuffer; -} tstrFifoHandler; - - -extern u32 FIFO_InitBuffer(tHANDLE *hBuffer, - u32 u32BufferLength); -extern u32 FIFO_DeInit(tHANDLE hFifo); -extern u32 FIFO_ReadBytes(tHANDLE hFifo, u8 *pu8Buffer, - u32 u32BytesToRead, u32 *pu32BytesRead); -extern u32 FIFO_WriteBytes(tHANDLE hFifo, u8 *pu8Buffer, - u32 u32BytesToWrite, bool bForceOverWrite); diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index c089e739465a..cc549c2c5213 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -9,7 +9,6 @@ extern u8 connecting; extern WILC_TimerHandle hDuringIpTimer; #endif -extern bool bEnablePS; /*BugID_5137*/ extern u8 g_wilc_initialized; /*****************************************************************************/ @@ -570,9 +569,7 @@ static u8 gs8GetIP[2][4]; static u32 gu32InactiveTime; static u8 gu8DelBcn; #endif -#ifndef SIMULATION static u32 gu32WidConnRstHack; -#endif /*BugID_5137*/ u8 *gu8FlushedJoinReq; @@ -803,7 +800,7 @@ s32 Handle_get_IPAddress(void *drvHandler, u8 *pu8IPAddr, u8 idx) /*get the value by searching the local copy*/ WILC_FREE(strWID.ps8WidVal); - if (WILC_memcmp(gs8GetIP[idx], gs8SetIP[idx], IP_ALEN) != 0) + if (memcmp(gs8GetIP[idx], gs8SetIP[idx], IP_ALEN) != 0) host_int_setup_ipaddress((WILC_WFIDrvHandle)pstrWFIDrv, gs8SetIP[idx], idx); if (s32Error != WILC_SUCCESS) { @@ -1353,11 +1350,10 @@ static s32 Handle_Scan(void *drvHandler, tstrHostIFscanAttr *pstrHostIFscanAttr) /*keep the state as is , no need to change it*/ /* gWFiDrvHandle->enuHostIFstate = HOST_IF_SCANNING; */ - if (pstrWFIDrv->enuHostIFstate == HOST_IF_CONNECTED) { + if (pstrWFIDrv->enuHostIFstate == HOST_IF_CONNECTED) gbScanWhileConnected = true; - } else if (pstrWFIDrv->enuHostIFstate == HOST_IF_IDLE) { + else if (pstrWFIDrv->enuHostIFstate == HOST_IF_IDLE) gbScanWhileConnected = false; - } s32Error = SendConfigPkt(SET_CFG, strWIDList, u32WidsCount, false, (u32)pstrWFIDrv); @@ -1496,8 +1492,8 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon PRINT_D(GENERIC_DBG, "Handling connect request\n"); #ifndef CONNECT_DIRECT - WILC_memset(gapu8RcvdSurveyResults[0], 0, MAX_SURVEY_RESULT_FRAG_SIZE); - WILC_memset(gapu8RcvdSurveyResults[1], 0, MAX_SURVEY_RESULT_FRAG_SIZE); + memset(gapu8RcvdSurveyResults[0], 0, MAX_SURVEY_RESULT_FRAG_SIZE); + memset(gapu8RcvdSurveyResults[1], 0, MAX_SURVEY_RESULT_FRAG_SIZE); PRINT_D(HOSTINF_DBG, "Getting site survey results\n"); @@ -1529,7 +1525,7 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon for (i = 0; i < pstrWFIDrv->u32SurveyResultsCount; i++) { - if (WILC_memcmp(pstrWFIDrv->astrSurveyResults[i].SSID, + if (memcmp(pstrWFIDrv->astrSurveyResults[i].SSID, pstrHostIFconnectAttr->pu8ssid, pstrHostIFconnectAttr->ssidLen) == 0) { PRINT_INFO(HOSTINF_DBG, "Network with required SSID is found %s\n", pstrHostIFconnectAttr->pu8ssid); @@ -1542,7 +1538,7 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon /* BSSID is also passed from the user, so decision of matching * should consider also this passed BSSID */ - if (WILC_memcmp(pstrWFIDrv->astrSurveyResults[i].BSSID, + if (memcmp(pstrWFIDrv->astrSurveyResults[i].BSSID, pstrHostIFconnectAttr->pu8bssid, 6) == 0) { PRINT_INFO(HOSTINF_DBG, "BSSID is passed from the user and matched\n"); @@ -1626,14 +1622,12 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon strWIDList[u32WidsCount].ps8WidVal = (s8 *)&u8bssDscListIndex; u32WidsCount++; - #ifndef SIMULATION /* A temporary workaround to avoid handling the misleading MAC_DISCONNECTED raised from the * firmware at chip reset when processing the WIDs of the Connect Request. * (This workaround should be removed in the future when the Chip reset of the Connect WIDs is disabled) */ /* ////////////////////// */ gu32WidConnRstHack = 0; /* ////////////////////// */ - #endif s32Error = SendConfigPkt(SET_CFG, strWIDList, u32WidsCount, false, (u32)pstrWFIDrv); if (s32Error) { @@ -1652,7 +1646,7 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon /* if we try to connect to an already connected AP then discard the request */ - if (WILC_memcmp(pstrHostIFconnectAttr->pu8bssid, u8ConnectedSSID, ETH_ALEN) == 0) { + if (memcmp(pstrHostIFconnectAttr->pu8bssid, u8ConnectedSSID, ETH_ALEN) == 0) { s32Error = WILC_SUCCESS; PRINT_ER("Trying to connect to an already connected AP, Discard connect request\n"); @@ -1724,7 +1718,7 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon u32WidsCount++; /*BugID_5137*/ - if (WILC_memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) { + if (memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) { gu32FlushedInfoElemAsocSize = pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen; gu8FlushedInfoElemAsoc = WILC_MALLOC(gu32FlushedInfoElemAsocSize); @@ -1739,7 +1733,7 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon u32WidsCount++; /*BugID_5137*/ - if (WILC_memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) + if (memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) gu8Flushed11iMode = pstrWFIDrv->strWILC_UsrConnReq.u8security; PRINT_INFO(HOSTINF_DBG, "Encrypt Mode = %x\n", pstrWFIDrv->strWILC_UsrConnReq.u8security); @@ -1752,7 +1746,7 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon u32WidsCount++; /*BugID_5137*/ - if (WILC_memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) + if (memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) gu8FlushedAuthType = (u8)pstrWFIDrv->strWILC_UsrConnReq.tenuAuth_type; PRINT_INFO(HOSTINF_DBG, "Authentication Type = %x\n", pstrWFIDrv->strWILC_UsrConnReq.tenuAuth_type); @@ -1807,7 +1801,7 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon strWIDList[u32WidsCount].ps8WidVal = WILC_MALLOC(strWIDList[u32WidsCount].s32ValueSize); /*BugID_5137*/ - if (WILC_memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) { + if (memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) { gu32FlushedJoinReqSize = strWIDList[u32WidsCount].s32ValueSize; gu8FlushedJoinReq = WILC_MALLOC(gu32FlushedJoinReqSize); } @@ -1936,17 +1930,15 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon #endif /* #ifdef WILC_PARSE_SCAN_IN_HOST*/ u32WidsCount++; - #ifndef SIMULATION /* A temporary workaround to avoid handling the misleading MAC_DISCONNECTED raised from the * firmware at chip reset when processing the WIDs of the Connect Request. * (This workaround should be removed in the future when the Chip reset of the Connect WIDs is disabled) */ /* ////////////////////// */ gu32WidConnRstHack = 0; /* ////////////////////// */ - #endif /*BugID_5137*/ - if (WILC_memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) { + if (memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) { memcpy(gu8FlushedJoinReq, pu8CurrByte, gu32FlushedJoinReqSize); gu8FlushedJoinReqDrvHandler = (u32)pstrWFIDrv; } @@ -1978,7 +1970,7 @@ static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFcon PRINT_D(HOSTINF_DBG, "could not start connecting to the required network\n"); - WILC_memset(&strConnectInfo, 0, sizeof(tstrConnectInfo)); + memset(&strConnectInfo, 0, sizeof(tstrConnectInfo)); if (pstrHostIFconnectAttr->pfConnectResult != NULL) { if (pstrHostIFconnectAttr->pu8bssid != NULL) @@ -2130,7 +2122,7 @@ static s32 Handle_ConnectTimeout(void *drvHandler) gbScanWhileConnected = false; - WILC_memset(&strConnectInfo, 0, sizeof(tstrConnectInfo)); + memset(&strConnectInfo, 0, sizeof(tstrConnectInfo)); /* First, we will notify the upper layer with the Connection failure {through the Connect Callback function}, @@ -2196,7 +2188,7 @@ static s32 Handle_ConnectTimeout(void *drvHandler) pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = NULL; } - WILC_memset(u8ConnectedSSID, 0, ETH_ALEN); + memset(u8ConnectedSSID, 0, ETH_ALEN); /*BugID_5213*/ /*Freeing flushed join request params on connect timeout*/ if (gu8FlushedJoinReq != NULL && gu8FlushedJoinReqDrvHandler == (u32)drvHandler) { @@ -2252,7 +2244,7 @@ static s32 Handle_RcvdNtwrkInfo(void *drvHandler, tstrRcvdNetworkInfo *pstrRcvdN if ((pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[i].au8bssid != NULL) && (pstrNetworkInfo->au8bssid != NULL)) { - if (WILC_memcmp(pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[i].au8bssid, + if (memcmp(pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[i].au8bssid, pstrNetworkInfo->au8bssid, 6) == 0) { if (pstrNetworkInfo->s8rssi <= pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[i].s8rssi) { /*we have already found this network with better rssi, so keep the old cached one and don't @@ -2405,10 +2397,10 @@ static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pst PRINT_D(HOSTINF_DBG, "Recieved MAC status = %d with Reason = %d , Code = %d\n", u8MacStatus, u8MacStatusReasonCode, u8MacStatusAdditionalInfo); - WILC_memset(&strConnectInfo, 0, sizeof(tstrConnectInfo)); + memset(&strConnectInfo, 0, sizeof(tstrConnectInfo)); if (u8MacStatus == MAC_CONNECTED) { - WILC_memset(gapu8RcvdAssocResp, 0, MAX_ASSOC_RESP_FRAME_SIZE); + memset(gapu8RcvdAssocResp, 0, MAX_ASSOC_RESP_FRAME_SIZE); host_int_get_assoc_res_info((WILC_WFIDrvHandle)pstrWFIDrv, gapu8RcvdAssocResp, @@ -2455,11 +2447,11 @@ static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pst if ((u8MacStatus == MAC_CONNECTED) && (strConnectInfo.u16ConnectStatus != SUCCESSFUL_STATUSCODE)) { PRINT_ER("Received MAC status is MAC_CONNECTED while the received status code in Asoc Resp is not SUCCESSFUL_STATUSCODE\n"); - WILC_memset(u8ConnectedSSID, 0, ETH_ALEN); + memset(u8ConnectedSSID, 0, ETH_ALEN); } else if (u8MacStatus == MAC_DISCONNECTED) { PRINT_ER("Received MAC status is MAC_DISCONNECTED\n"); - WILC_memset(u8ConnectedSSID, 0, ETH_ALEN); + memset(u8ConnectedSSID, 0, ETH_ALEN); } /* TODO: mostafa: correct BSSID should be retrieved from actual BSSID received from AP */ @@ -2560,7 +2552,7 @@ static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pst /* Disassociation or Deauthentication frame has been received */ PRINT_D(HOSTINF_DBG, "Received MAC_DISCONNECTED from the FW\n"); - WILC_memset(&strDisconnectNotifInfo, 0, sizeof(tstrDisconnectNotifInfo)); + memset(&strDisconnectNotifInfo, 0, sizeof(tstrDisconnectNotifInfo)); if (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult) { PRINT_D(HOSTINF_DBG, "\n\n<< Abort the running OBSS Scan >>\n\n"); @@ -2589,7 +2581,7 @@ static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pst PRINT_ER("Connect result callback function is NULL\n"); } - WILC_memset(pstrWFIDrv->au8AssociatedBSSID, 0, ETH_ALEN); + memset(pstrWFIDrv->au8AssociatedBSSID, 0, ETH_ALEN); /* Deallocation */ @@ -2797,7 +2789,7 @@ static int Handle_Key(void *drvHandler, tstrHostIFkeyAttr *pstrHostIFkeyAttr) goto _WPARxGtk_end_case_; } - WILC_memset(pu8keybuf, 0, RX_MIC_KEY_MSG_LEN); + memset(pu8keybuf, 0, RX_MIC_KEY_MSG_LEN); /*|----------------------------------------------------------------------------| @@ -2848,7 +2840,7 @@ static int Handle_Key(void *drvHandler, tstrHostIFkeyAttr *pstrHostIFkeyAttr) goto _WPARxGtk_end_case_; } - WILC_memset(pu8keybuf, 0, RX_MIC_KEY_MSG_LEN); + memset(pu8keybuf, 0, RX_MIC_KEY_MSG_LEN); /*|----------------------------------------------------------------------------| @@ -2856,11 +2848,10 @@ static int Handle_Key(void *drvHandler, tstrHostIFkeyAttr *pstrHostIFkeyAttr) * |------------|---------|-------|------------|---------------|----------------| | 6 bytes | 8 byte |1 byte | 1 byte | 16 bytes | 8 bytes |*/ - if (pstrWFIDrv->enuHostIFstate == HOST_IF_CONNECTED) { + if (pstrWFIDrv->enuHostIFstate == HOST_IF_CONNECTED) WILC_memcpy(pu8keybuf, pstrWFIDrv->au8AssociatedBSSID, ETH_ALEN); - } else { + else PRINT_ER("Couldn't handle WPARxGtk while enuHostIFstate is not HOST_IF_CONNECTED\n"); - } WILC_memcpy(pu8keybuf + 6, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq, 8); @@ -3059,7 +3050,7 @@ static void Handle_Disconnect(void *drvHandler) host_int_set_power_mgmt((WILC_WFIDrvHandle)pstrWFIDrv, 0, 0); #endif - WILC_memset(u8ConnectedSSID, 0, ETH_ALEN); + memset(u8ConnectedSSID, 0, ETH_ALEN); s32Error = SendConfigPkt(SET_CFG, &strWID, 1, false, (u32)pstrWFIDrv); @@ -3069,7 +3060,7 @@ static void Handle_Disconnect(void *drvHandler) } else { tstrDisconnectNotifInfo strDisconnectNotifInfo; - WILC_memset(&strDisconnectNotifInfo, 0, sizeof(tstrDisconnectNotifInfo)); + memset(&strDisconnectNotifInfo, 0, sizeof(tstrDisconnectNotifInfo)); strDisconnectNotifInfo.u16reason = 0; strDisconnectNotifInfo.ie = NULL; @@ -3102,7 +3093,7 @@ static void Handle_Disconnect(void *drvHandler) pstrWFIDrv->enuHostIFstate = HOST_IF_IDLE; - WILC_memset(pstrWFIDrv->au8AssociatedBSSID, 0, ETH_ALEN); + memset(pstrWFIDrv->au8AssociatedBSSID, 0, ETH_ALEN); /* Deallocation */ @@ -3996,7 +3987,7 @@ static void ListenTimerCB(void *pvArg) WILC_TimerStop(&(pstrWFIDrv->hRemainOnChannel), NULL); /* prepare the Timer Callback message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_LISTEN_TIMER_FIRED; strHostIFmsg.drvHandler = pstrWFIDrv; strHostIFmsg.uniHostIFmsgBody.strHostIfRemainOnChan.u32ListenSessionID = pstrWFIDrv->strHostIfRemainOnChan.u32ListenSessionID; @@ -4031,11 +4022,10 @@ static void Handle_PowerManagement(void *drvHandler, tstrHostIfPowerMgmtParam *s strWID.u16WIDid = (u16)WID_POWER_MANAGEMENT; - if (strPowerMgmtParam->bIsEnabled == true) { + if (strPowerMgmtParam->bIsEnabled == true) s8PowerMode = MIN_FAST_PS; - } else { + else s8PowerMode = NO_POWERSAVE; - } PRINT_D(HOSTINF_DBG, "Handling power mgmt to %d\n", s8PowerMode); strWID.ps8WidVal = &s8PowerMode; strWID.s32ValueSize = sizeof(char); @@ -4335,7 +4325,7 @@ static int hostIFthread(void *pvArg) tstrHostIFmsg strHostIFmsg; tstrWILC_WFIDrv *pstrWFIDrv; - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); while (1) { WILC_MsgQueueRecv(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), &u32Ret, NULL); @@ -4557,7 +4547,7 @@ static void TimerCB_Scan(void *pvArg) tstrHostIFmsg strHostIFmsg; /* prepare the Timer Callback message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.drvHandler = pvArg; strHostIFmsg.u16MsgId = HOST_IF_MSG_SCAN_TIMER_FIRED; @@ -4570,7 +4560,7 @@ static void TimerCB_Connect(void *pvArg) tstrHostIFmsg strHostIFmsg; /* prepare the Timer Callback message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.drvHandler = pvArg; strHostIFmsg.u16MsgId = HOST_IF_MSG_CONNECT_TIMER_FIRED; @@ -4632,7 +4622,7 @@ s32 host_int_remove_wep_key(WILC_WFIDrvHandle hWFIDrv, u8 u8keyIdx) WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); /* prepare the Remove Wep Key Message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY; @@ -4681,7 +4671,7 @@ s32 host_int_set_WEPDefaultKeyID(WILC_WFIDrvHandle hWFIDrv, u8 u8Index) WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); /* prepare the Key Message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY; @@ -4738,7 +4728,7 @@ s32 host_int_add_wep_key_bss_sta(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey, /* prepare the Key Message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY; @@ -4804,7 +4794,7 @@ s32 host_int_add_wep_key_bss_ap(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey, /* prepare the Key Message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); if (INFO) { for (i = 0; i < u8WepKeylen; i++) @@ -4883,7 +4873,7 @@ s32 host_int_add_ptk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8Ptk, u8 u8PtkKeylen u8KeyLen += TX_MIC_KEY_LEN; /* prepare the Key Message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY; @@ -4978,7 +4968,7 @@ s32 host_int_add_rx_gtk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8RxGtk, u8 u8GtkK if (pstrWFIDrv == NULL) WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); /* prepare the Key Message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); if (pu8RxMic != NULL) @@ -5085,7 +5075,7 @@ s32 host_int_set_pmkid_info(WILC_WFIDrvHandle hWFIDrv, tstrHostIFpmkidAttr *pu8P WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); /* prepare the Key Message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY; strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.enuKeyType = PMKSA; @@ -5200,7 +5190,7 @@ s32 host_int_get_MacAddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8MacAddress) /* prepare the Message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_MAC_ADDRESS; strHostIFmsg.uniHostIFmsgBody.strHostIfGetMacAddress.u8MacAddress = pu8MacAddress; @@ -5235,7 +5225,7 @@ s32 host_int_set_MacAddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8MacAddress) PRINT_D(GENERIC_DBG, "mac addr = %x:%x:%x\n", pu8MacAddress[0], pu8MacAddress[1], pu8MacAddress[2]); /* prepare setting mac address message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_SET_MAC_ADDRESS; WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIfSetMacAddress.u8MacAddress, pu8MacAddress, ETH_ALEN); strHostIFmsg.drvHandler = hWFIDrv; @@ -5454,7 +5444,7 @@ s32 host_int_set_join_req(WILC_WFIDrvHandle hWFIDrv, u8 *pu8bssid, * } */ /* prepare the Connect Message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_CONNECT; @@ -5486,9 +5476,9 @@ s32 host_int_set_join_req(WILC_WFIDrvHandle hWFIDrv, u8 *pu8bssid, WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8IEs, pu8IEs, IEsLen); } - if (pstrWFIDrv->enuHostIFstate < HOST_IF_CONNECTING) { + if (pstrWFIDrv->enuHostIFstate < HOST_IF_CONNECTING) pstrWFIDrv->enuHostIFstate = HOST_IF_CONNECTING; - } else + else PRINT_D(GENERIC_DBG, "Don't set state to 'connecting' as state is %d\n", pstrWFIDrv->enuHostIFstate); /* send the message */ @@ -5581,7 +5571,7 @@ s32 host_int_disconnect(WILC_WFIDrvHandle hWFIDrv, u16 u16ReasonCode) } /* prepare the Disconnect Message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_DISCONNECT; strHostIFmsg.drvHandler = hWFIDrv; @@ -5771,7 +5761,7 @@ s32 host_int_set_mac_chnl_num(WILC_WFIDrvHandle hWFIDrv, u8 u8ChNum) WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); /* prepare the set channel message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_SET_CHANNEL; strHostIFmsg.uniHostIFmsgBody.strHostIFSetChan.u8SetChan = u8ChNum; strHostIFmsg.drvHandler = hWFIDrv; @@ -5796,7 +5786,7 @@ s32 host_int_wait_msg_queue_idle(void) /* prepare the set driver handler message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_Q_IDLE; s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL); if (s32Error) @@ -5822,7 +5812,7 @@ s32 host_int_set_wfi_drv_handler(u32 u32address) /* prepare the set driver handler message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_SET_WFIDRV_HANDLER; strHostIFmsg.uniHostIFmsgBody.strHostIfSetDrvHandler.u32Address = u32address; /* strHostIFmsg.drvHandler=hWFIDrv; */ @@ -5849,7 +5839,7 @@ s32 host_int_set_operation_mode(WILC_WFIDrvHandle hWFIDrv, u32 u32mode) /* prepare the set driver handler message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_SET_OPERATION_MODE; strHostIFmsg.uniHostIFmsgBody.strHostIfSetOperationMode.u32Mode = u32mode; strHostIFmsg.drvHandler = hWFIDrv; @@ -5892,7 +5882,7 @@ s32 host_int_get_host_chnl_num(WILC_WFIDrvHandle hWFIDrv, u8 *pu8ChNo) } /* prepare the Get Channel Message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_CHNL; strHostIFmsg.drvHandler = hWFIDrv; @@ -5984,7 +5974,7 @@ s32 host_int_get_inactive_time(WILC_WFIDrvHandle hWFIDrv, const u8 *mac, u32 *pu WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); } - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIfStaInactiveT.mac, @@ -6076,7 +6066,7 @@ s32 host_int_get_rssi(WILC_WFIDrvHandle hWFIDrv, s8 *ps8Rssi) /* prepare the Get RSSI Message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_RSSI; strHostIFmsg.drvHandler = hWFIDrv; @@ -6113,7 +6103,7 @@ s32 host_int_get_link_speed(WILC_WFIDrvHandle hWFIDrv, s8 *ps8lnkspd) /* prepare the Get LINKSPEED Message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_LINKSPEED; strHostIFmsg.drvHandler = hWFIDrv; @@ -6147,7 +6137,7 @@ s32 host_int_get_statistics(WILC_WFIDrvHandle hWFIDrv, tstrStatistics *pstrStati /* prepare the Get RSSI Message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_STATISTICS; strHostIFmsg.uniHostIFmsgBody.pUserData = (char *)pstrStatistics; @@ -6196,7 +6186,7 @@ s32 host_int_scan(WILC_WFIDrvHandle hWFIDrv, u8 u8ScanSource, /* prepare the Scan Message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_SCAN; @@ -6265,7 +6255,7 @@ s32 hif_set_cfg(WILC_WFIDrvHandle hWFIDrv, tstrCfgParamVal *pstrCfgParamVal) if (pstrWFIDrv == NULL) WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); /* prepare the WiphyParams Message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_CFG_PARAMS; strHostIFmsg.uniHostIFmsgBody.strHostIFCfgParamAttr.pstrCfgParamVal = *pstrCfgParamVal; strHostIFmsg.drvHandler = hWFIDrv; @@ -6443,7 +6433,7 @@ void GetPeriodicRSSI(void *pvArg) tstrHostIFmsg strHostIFmsg; /* prepare the Get RSSI Message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_RSSI; strHostIFmsg.drvHandler = pstrWFIDrv; @@ -6503,7 +6493,7 @@ s32 host_int_init(WILC_WFIDrvHandle *phWFIDrv) PRINT_ER("Failed to allocate memory\n"); goto _fail_timer_2; } - WILC_memset(pstrWFIDrv, 0, sizeof(tstrWILC_WFIDrv)); + memset(pstrWFIDrv, 0, sizeof(tstrWILC_WFIDrv)); /*return driver handle to user*/ *phWFIDrv = (WILC_WFIDrvHandle)pstrWFIDrv; /*save into globl handle*/ @@ -6586,12 +6576,6 @@ s32 host_int_init(WILC_WFIDrvHandle *phWFIDrv) sema_init(&(pstrWFIDrv->gtOsCfgValuesSem), 1); down(&(pstrWFIDrv->gtOsCfgValuesSem)); - - -#ifdef SIMULATION - TransportInit(); -#endif - pstrWFIDrv->enuHostIFstate = HOST_IF_IDLE; /* gWFiDrvHandle->bPendingConnRequest = false; */ @@ -6627,11 +6611,6 @@ s32 host_int_init(WILC_WFIDrvHandle *phWFIDrv) goto _fail_mem_; } -#ifdef SIMULATION - /*Initialize Simulaor*/ - CoreConfigSimulatorInit(); -#endif - u32Intialized = 1; clients_count++; /* increase number of created entities */ @@ -6731,19 +6710,13 @@ s32 host_int_deinit(WILC_WFIDrvHandle hWFIDrv) pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult = NULL; } /*deinit configurator and simulator*/ -#ifdef SIMULATION - CoreConfigSimulatorDeInit(); -#endif CoreConfiguratorDeInit(); -#ifdef SIMULATION - TransportDeInit(); -#endif pstrWFIDrv->enuHostIFstate = HOST_IF_IDLE; gbScanWhileConnected = false; - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); if (clients_count == 1) { if (WILC_TimerDestroy(&g_hPeriodicRSSI, NULL)) { @@ -6814,7 +6787,7 @@ void NetworkInfoReceived(u8 *pu8Buffer, u32 u32Length) } /* prepare the Asynchronous Network Info message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_RCVD_NTWRK_INFO; strHostIFmsg.drvHandler = pstrWFIDrv; @@ -6875,7 +6848,7 @@ void GnrlAsyncInfoReceived(u8 *pu8Buffer, u32 u32Length) } /* prepare the General Asynchronous Info message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_RCVD_GNRL_ASYNC_INFO; @@ -6925,7 +6898,7 @@ void host_int_ScanCompleteReceived(u8 *pu8Buffer, u32 u32Length) /*if there is an ongoing scan request*/ if (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult) { /* prepare theScan Done message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_RCVD_SCAN_COMPLETE; strHostIFmsg.drvHandler = pstrWFIDrv; @@ -6975,7 +6948,7 @@ s32 host_int_remain_on_channel(WILC_WFIDrvHandle hWFIDrv, u32 u32SessionID, u32 WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); /* prepare the remainonchan Message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); /* prepare the WiphyParams Message */ strHostIFmsg.u16MsgId = HOST_IF_MSG_REMAIN_ON_CHAN; @@ -7025,7 +6998,7 @@ s32 host_int_ListenStateExpired(WILC_WFIDrvHandle hWFIDrv, u32 u32SessionID) WILC_TimerStop(&(pstrWFIDrv->hRemainOnChannel), NULL); /* prepare the timer fire Message */ - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); strHostIFmsg.u16MsgId = HOST_IF_MSG_LISTEN_TIMER_FIRED; strHostIFmsg.drvHandler = hWFIDrv; strHostIFmsg.uniHostIFmsgBody.strHostIfRemainOnChan.u32ListenSessionID = u32SessionID; @@ -7057,7 +7030,7 @@ s32 host_int_frame_register(WILC_WFIDrvHandle hWFIDrv, u16 u16FrameType, bool bR if (pstrWFIDrv == NULL) WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); /* prepare the WiphyParams Message */ strHostIFmsg.u16MsgId = HOST_IF_MSG_REGISTER_FRAME; @@ -7119,7 +7092,7 @@ s32 host_int_add_beacon(WILC_WFIDrvHandle hWFIDrv, u32 u32Interval, if (pstrWFIDrv == NULL) WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); PRINT_D(HOSTINF_DBG, "Setting adding beacon message queue params\n"); @@ -7217,7 +7190,7 @@ s32 host_int_add_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrSt if (pstrWFIDrv == NULL) WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); PRINT_D(HOSTINF_DBG, "Setting adding station message queue params\n"); @@ -7266,7 +7239,7 @@ s32 host_int_del_station(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8MacAddr) if (pstrWFIDrv == NULL) WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); PRINT_D(HOSTINF_DBG, "Setting deleting station message queue params\n"); @@ -7278,7 +7251,7 @@ s32 host_int_del_station(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8MacAddr) /*BugID_4795: Handling situation of deleting all stations*/ if (pu8MacAddr == NULL) - WILC_memset(pstrDelStationMsg->au8MacAddr, 255, ETH_ALEN); + memset(pstrDelStationMsg->au8MacAddr, 255, ETH_ALEN); else WILC_memcpy(pstrDelStationMsg->au8MacAddr, pu8MacAddr, ETH_ALEN); @@ -7314,7 +7287,7 @@ s32 host_int_del_allstation(WILC_WFIDrvHandle hWFIDrv, u8 pu8MacAddr[][ETH_ALEN] if (pstrWFIDrv == NULL) WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); PRINT_D(HOSTINF_DBG, "Setting deauthenticating station message queue params\n"); @@ -7374,7 +7347,7 @@ s32 host_int_edit_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrS PRINT_D(HOSTINF_DBG, "Setting editing station message queue params\n"); - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); /* prepare the WiphyParams Message */ @@ -7415,7 +7388,7 @@ s32 host_int_set_power_mgmt(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled, u32 u32T PRINT_D(HOSTINF_DBG, "Setting Power management message queue params\n"); - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); /* prepare the WiphyParams Message */ @@ -7449,7 +7422,7 @@ s32 host_int_setup_multicast_filter(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled, PRINT_D(HOSTINF_DBG, "Setting Multicast Filter params\n"); - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); /* prepare the WiphyParams Message */ @@ -7502,7 +7475,7 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo) pNewJoinBssParam = WILC_MALLOC(sizeof(tstrJoinBssParam)); if (pNewJoinBssParam != NULL) { - WILC_memset(pNewJoinBssParam, 0, sizeof(tstrJoinBssParam)); + memset(pNewJoinBssParam, 0, sizeof(tstrJoinBssParam)); pNewJoinBssParam->dtim_period = ptstrNetworkInfo->u8DtimPeriod; pNewJoinBssParam->beacon_period = ptstrNetworkInfo->u16BeaconPeriod; pNewJoinBssParam->cap_info = ptstrNetworkInfo->u16CapInfo; @@ -7511,8 +7484,8 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo) * PRINT_D(HOSTINF_DBG,"%c",pNewJoinBssParam->au8bssid[i]);*/ WILC_memcpy((u8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->au8ssid, ptstrNetworkInfo->u8SsidLen + 1); pNewJoinBssParam->ssidLen = ptstrNetworkInfo->u8SsidLen; - WILC_memset(pNewJoinBssParam->rsn_pcip_policy, 0xFF, 3); - WILC_memset(pNewJoinBssParam->rsn_auth_policy, 0xFF, 3); + memset(pNewJoinBssParam->rsn_pcip_policy, 0xFF, 3); + memset(pNewJoinBssParam->rsn_auth_policy, 0xFF, 3); /*for(i=0; i<pNewJoinBssParam->ssidLen;i++) * PRINT_D(HOSTINF_DBG,"%c",pNewJoinBssParam->ssid[i]);*/ @@ -7716,7 +7689,7 @@ static int host_int_addBASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char T if (pstrWFIDrv == NULL) WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); /* prepare the WiphyParams Message */ strHostIFmsg.u16MsgId = HOST_IF_MSG_ADD_BA_SESSION; @@ -7749,7 +7722,7 @@ s32 host_int_delBASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID) if (pstrWFIDrv == NULL) WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); /* prepare the WiphyParams Message */ strHostIFmsg.u16MsgId = HOST_IF_MSG_DEL_BA_SESSION; @@ -7782,7 +7755,7 @@ s32 host_int_del_All_Rx_BASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char if (pstrWFIDrv == NULL) WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); /* prepare the WiphyParams Message */ strHostIFmsg.u16MsgId = HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS; @@ -7825,7 +7798,7 @@ s32 host_int_setup_ipaddress(WILC_WFIDrvHandle hWFIDrv, u8 *u16ipadd, u8 idx) if (pstrWFIDrv == NULL) WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); /* prepare the WiphyParams Message */ strHostIFmsg.u16MsgId = HOST_IF_MSG_SET_IPADDRESS; @@ -7864,7 +7837,7 @@ s32 host_int_get_ipaddress(WILC_WFIDrvHandle hWFIDrv, u8 *u16ipadd, u8 idx) if (pstrWFIDrv == NULL) WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT); - WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); + memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg)); /* prepare the WiphyParams Message */ strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_IPADDRESS; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 38db740745cd..cdfb43a2b144 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -11,7 +11,6 @@ #define HOST_INT_H #include "coreconfigurator.h" -#include "coreconfigsimulator.h" /*****************************************************************************/ /* Macros */ /*****************************************************************************/ diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index d812a3b194f3..123468a9582f 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -6,20 +6,15 @@ * @date 01 MAR 2012 * @version 1.0 */ - -#ifndef SIMULATION #include "wilc_wfi_cfgoperations.h" #include "linux_wlan_common.h" #include "wilc_wlan_if.h" #include "wilc_wlan.h" -#endif + #ifdef WILC_FULLY_HOSTING_AP #include "wilc_host_ap.h" #endif #ifdef WILC_AP_EXTERNAL_MLME -#ifdef SIMULATION -#include "wilc_wfi_cfgoperations.h" -#endif struct wilc_wfi_radiotap_hdr { struct ieee80211_radiotap_header hdr; @@ -39,9 +34,7 @@ extern linux_wlan_t *g_linux_wlan; static struct net_device *wilc_wfi_mon; /* global monitor netdev */ -#ifdef SIMULATION -extern int WILC_WFI_Tx(struct sk_buff *skb, struct net_device *dev); -#elif USE_WIRELESS +#if USE_WIRELESS extern int mac_xmit(struct sk_buff *skb, struct net_device *dev); #endif @@ -374,9 +367,7 @@ static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb, PRINT_INFO(HOSTAPD_DBG, "SKB netdevice name = %s\n", skb->dev->name); PRINT_INFO(HOSTAPD_DBG, "MONITOR real dev name = %s\n", mon_priv->real_ndev->name); - #ifdef SIMULATION - ret = WILC_WFI_Tx(skb, mon_priv->real_ndev); - #elif USE_WIRELESS + #if USE_WIRELESS /* Identify if Ethernet or MAC header (data or mgmt) */ memcpy(srcAdd, &skb->data[10], 6); memcpy(bssid, &skb->data[16], 6); @@ -567,7 +558,7 @@ struct net_device *WILC_WFI_init_mon_interface(const char *name, struct net_devi * @date 12 JUL 2012 * @version 1.0 */ -int WILC_WFI_deinit_mon_interface() +int WILC_WFI_deinit_mon_interface(void) { bool rollback_lock = false; diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 5a794df0da4d..1384846a5d01 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -1,4 +1,3 @@ -#ifndef SIMULATION #include "wilc_wfi_cfgoperations.h" #include "linux_wlan_common.h" #include "wilc_wlan_if.h" @@ -103,7 +102,6 @@ static int linux_wlan_device_detection(int on_off) return 0; } - #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP static int dev_state_ev_handler(struct notifier_block *this, unsigned long event, void *ptr); @@ -116,7 +114,6 @@ static struct notifier_block g_dev_notifier = { if (g_linux_wlan->oup.wlan_cleanup != NULL) \ g_linux_wlan->oup.wlan_cleanup(); } - #ifndef STA_FIRMWARE #define STA_FIRMWARE "wifi_firmware.bin" #endif @@ -129,15 +126,12 @@ static struct notifier_block g_dev_notifier = { #define P2P_CONCURRENCY_FIRMWARE "wifi_firmware_p2p_concurrency.bin" #endif - - typedef struct android_wifi_priv_cmd { char *buf; int used_len; int total_len; } android_wifi_priv_cmd; - #define IRQ_WAIT 1 #define IRQ_NO_WAIT 0 /* @@ -158,7 +152,6 @@ void linux_wlan_unlock(void *vp); extern void WILC_WFI_monitor_rx(uint8_t *buff, uint32_t size); extern void WILC_WFI_p2p_rx(struct net_device *dev, uint8_t *buff, uint32_t size); - static void *internal_alloc(uint32_t size, uint32_t flag); static void linux_wlan_tx_complete(void *priv, int status); void frmw_to_linux(uint8_t *buff, uint32_t size, uint32_t pkt_offset); @@ -170,8 +163,6 @@ static struct net_device_stats *mac_stats(struct net_device *dev); static int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd); static void wilc_set_multicast_list(struct net_device *dev); - - /* * for now - in frmw_to_linux there should be private data to be passed to it * and this data should be pointer to net device @@ -200,22 +191,18 @@ volatile int WatchDogdebuggerCounter; char DebugBuffer[DEGUG_BUFFER_LENGTH + 20] = {0}; static char *ps8current = DebugBuffer; - - void printk_later(const char *format, ...) { va_list args; - va_start (args, format); - ps8current += vsprintf (ps8current, format, args); - va_end (args); - if ((ps8current - DebugBuffer) > DEGUG_BUFFER_LENGTH) { + va_start(args, format); + ps8current += vsprintf(ps8current, format, args); + va_end(args); + if ((ps8current - DebugBuffer) > DEGUG_BUFFER_LENGTH) ps8current = DebugBuffer; - } } - -void dump_logs() +void dump_logs(void) { if (DebugBuffer[0]) { DebugBuffer[DEGUG_BUFFER_LENGTH] = 0; @@ -229,7 +216,7 @@ void dump_logs() } } -void Reset_WatchDogdebugger() +void Reset_WatchDogdebugger(void) { WatchDogdebuggerCounter = 0; } @@ -246,11 +233,8 @@ static int DebuggingThreadTask(void *vp) WatchDogdebuggerCounter = 0; } } - - #endif - #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP static int dev_state_ev_handler(struct notifier_block *this, unsigned long event, void *ptr) { @@ -298,7 +282,6 @@ static int dev_state_ev_handler(struct notifier_block *this, unsigned long event PRINT_INFO(GENERIC_DBG, "\n ============== IP Address Obtained ===============\n\n"); - /*If we are in station mode or client mode*/ if (nic->iftype == STATION_MODE || nic->iftype == CLIENT_MODE) { pstrWFIDrv->IFC_UP = 1; @@ -307,15 +290,13 @@ static int dev_state_ev_handler(struct notifier_block *this, unsigned long event PRINT_D(GENERIC_DBG, "IP obtained , enable scan\n"); } - - if (bEnablePS) host_int_set_power_mgmt((WILC_WFIDrvHandle)pstrWFIDrv, 1, 0); PRINT_D(GENERIC_DBG, "[%s] Up IP\n", dev_iface->ifa_label); pIP_Add_buff = (char *) (&(dev_iface->ifa_address)); - PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d \n", pIP_Add_buff[0], pIP_Add_buff[1], pIP_Add_buff[2], pIP_Add_buff[3]); + PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d\n", pIP_Add_buff[0], pIP_Add_buff[1], pIP_Add_buff[2], pIP_Add_buff[3]); host_int_setup_ipaddress((WILC_WFIDrvHandle)pstrWFIDrv, pIP_Add_buff, nic->u8IfIdx); break; @@ -334,11 +315,10 @@ static int dev_state_ev_handler(struct notifier_block *this, unsigned long event resolve_disconnect_aberration(pstrWFIDrv); - PRINT_D(GENERIC_DBG, "[%s] Down IP\n", dev_iface->ifa_label); pIP_Add_buff = null_ip; - PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d \n", pIP_Add_buff[0], pIP_Add_buff[1], pIP_Add_buff[2], pIP_Add_buff[3]); + PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d\n", pIP_Add_buff[0], pIP_Add_buff[1], pIP_Add_buff[2], pIP_Add_buff[3]); host_int_setup_ipaddress((WILC_WFIDrvHandle)pstrWFIDrv, pIP_Add_buff, nic->u8IfIdx); @@ -387,8 +367,6 @@ void linux_wlan_disable_irq(int wait) #if (defined WILC_SPI) || (defined WILC_SDIO_IRQ_GPIO) static irqreturn_t isr_uh_routine(int irq, void *user_data) { - - int_rcvdU++; #if (RX_BH_TYPE != RX_BH_THREADED_IRQ) linux_wlan_disable_irq(IRQ_NO_WAIT); @@ -440,19 +418,14 @@ static void isr_bh_routine(struct work_struct *work) #else return; #endif - - - } int_rcvdB++; PRINT_D(INT_DBG, "Interrupt received BH\n"); - if (g_linux_wlan->oup.wlan_handle_rx_isr != 0) { + if (g_linux_wlan->oup.wlan_handle_rx_isr != 0) g_linux_wlan->oup.wlan_handle_rx_isr(); - } else { + else PRINT_ER("wlan_handle_rx_isr() hasn't been initialized\n"); - } - #if (RX_BH_TYPE == RX_BH_THREADED_IRQ) return IRQ_HANDLED; @@ -476,18 +449,16 @@ static int isr_bh_routine(void *vp) } int_rcvdB++; PRINT_D(INT_DBG, "Interrupt received BH\n"); - if (g_linux_wlan->oup.wlan_handle_rx_isr != 0) { + if (g_linux_wlan->oup.wlan_handle_rx_isr != 0) g_linux_wlan->oup.wlan_handle_rx_isr(); - } else { + else PRINT_ER("wlan_handle_rx_isr() hasn't been initialized\n"); - } } return 0; } #endif - #if (defined WILC_SPI) || (defined WILC_SDIO_IRQ_GPIO) static int init_irq(linux_wlan_t *p_nic) { @@ -504,9 +475,9 @@ static int init_irq(linux_wlan_t *p_nic) * * ex) nic->dev_irq_num = gpio_to_irq(GPIO_NUM); */ -#elif defined (NM73131_0_BOARD) +#elif defined(NM73131_0_BOARD) nic->dev_irq_num = IRQ_WILC1000; -#elif defined (PANDA_BOARD) +#elif defined(PANDA_BOARD) gpio_export(GPIO_NUM, 1); nic->dev_irq_num = OMAP_GPIO_IRQ(GPIO_NUM); irq_set_irq_type(nic->dev_irq_num, IRQ_TYPE_LEVEL_LOW); @@ -518,7 +489,6 @@ static int init_irq(linux_wlan_t *p_nic) PRINT_ER("could not obtain gpio for WILC_INTR\n"); } - #if (RX_BH_TYPE == RX_BH_THREADED_IRQ) if ((ret != -1) && (request_threaded_irq(nic->dev_irq_num, isr_uh_routine, isr_bh_routine, IRQF_TRIGGER_LOW | IRQF_ONESHOT, /*Without IRQF_ONESHOT the uh will remain kicked in and dont gave a chance to bh*/ @@ -554,7 +524,6 @@ static void deinit_irq(linux_wlan_t *nic) #endif } - /* * OS functions */ @@ -601,7 +570,6 @@ void linux_wlan_free(void *vp) } } - static void *internal_alloc(uint32_t size, uint32_t flag) { char *pntr = NULL; @@ -610,7 +578,6 @@ static void *internal_alloc(uint32_t size, uint32_t flag) return (void *)pntr; } - static void linux_wlan_init_lock(char *lockName, void *plock, int count) { sema_init((struct semaphore *)plock, count); @@ -638,25 +605,22 @@ static int linux_wlan_lock_timeout(void *vp, u32 timeout) { int error = -1; PRINT_D(LOCK_DBG, "Locking %p\n", vp); - if (vp != NULL) { + if (vp != NULL) error = down_timeout((struct semaphore *)vp, msecs_to_jiffies(timeout)); - } else { + else PRINT_ER("Failed, mutex is NULL\n"); - } return error; } void linux_wlan_unlock(void *vp) { PRINT_D(LOCK_DBG, "Unlocking %p\n", vp); - if (vp != NULL) { + if (vp != NULL) up((struct semaphore *)vp); - } else { + else PRINT_ER("Failed, mutex is NULL\n"); - } } - static void linux_wlan_init_mutex(char *lockName, void *plock, int count) { mutex_init((struct mutex *)plock); @@ -702,7 +666,6 @@ static void linux_wlan_unlock_mutex(void *vp) } } - /*Added by Amr - BugID_4720*/ static void linux_wlan_init_spin_lock(char *lockName, void *plock, int count) { @@ -780,9 +743,8 @@ struct net_device *GetIfHandler(uint8_t *pMacHeader) } } PRINT_INFO(INIT_DBG, "Invalide handle\n"); - for (i = 0; i < 25; i++) { + for (i = 0; i < 25; i++) PRINT_D(INIT_DBG, "%02x ", pMacHeader[i]); - } Bssid = pMacHeader + 18; Bssid1 = pMacHeader + 12; for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) { @@ -822,9 +784,8 @@ int linux_wlan_get_num_conn_ifcs(void) uint8_t ret_val = 0; for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) { - if (memcmp(g_linux_wlan->strInterfaceInfo[i].aBSSID, null_bssid, 6)) { + if (memcmp(g_linux_wlan->strInterfaceInfo[i].aBSSID, null_bssid, 6)) ret_val++; - } } return ret_val; } @@ -913,15 +874,13 @@ static int linux_wlan_txq_task(void *vp) msleep(TX_BACKOFF_WEIGHT_UNIT_MS << backoff_weight); } while (/*timeout*/ 0); backoff_weight += TX_BACKOFF_WEIGHT_INCR_STEP; - if (backoff_weight > TX_BACKOFF_WEIGHT_MAX) { + if (backoff_weight > TX_BACKOFF_WEIGHT_MAX) backoff_weight = TX_BACKOFF_WEIGHT_MAX; - } } else { if (backoff_weight > TX_BACKOFF_WEIGHT_MIN) { backoff_weight -= TX_BACKOFF_WEIGHT_DECR_STEP; - if (backoff_weight < TX_BACKOFF_WEIGHT_MIN) { + if (backoff_weight < TX_BACKOFF_WEIGHT_MIN) backoff_weight = TX_BACKOFF_WEIGHT_MIN; - } } } /*TODO: drop packets after a certain time/number of retry count. */ @@ -944,7 +903,6 @@ int linux_wlan_get_firmware(perInterface_wlan_t *p_nic) const struct firmware *wilc_firmware; char *firmware; - if (nic->iftype == AP_MODE) firmware = AP_FIRMWARE; else if (nic->iftype == STATION_MODE) @@ -956,8 +914,6 @@ int linux_wlan_get_firmware(perInterface_wlan_t *p_nic) firmware = P2P_CONCURRENCY_FIRMWARE; } - - if (nic == NULL) { PRINT_ER("NIC is NULL\n"); goto _fail_; @@ -968,7 +924,6 @@ int linux_wlan_get_firmware(perInterface_wlan_t *p_nic) goto _fail_; } - /* the firmare should be located in /lib/firmware in * root file system with the name specified above */ @@ -1052,9 +1007,8 @@ static int linux_wlan_firmware_download(linux_wlan_t *p_nic) **/ PRINT_D(INIT_DBG, "Downloading Firmware ...\n"); ret = g_linux_wlan->oup.wlan_firmware_download(g_linux_wlan->wilc_firmware->data, g_linux_wlan->wilc_firmware->size); - if (ret < 0) { + if (ret < 0) goto _FAIL_; - } /* Freeing FW buffer */ PRINT_D(INIT_DBG, "Freeing FW buffer ...\n"); @@ -1062,13 +1016,12 @@ static int linux_wlan_firmware_download(linux_wlan_t *p_nic) release_firmware(g_linux_wlan->wilc_firmware); g_linux_wlan->wilc_firmware = NULL; - PRINT_D(INIT_DBG, "Download Succeeded \n"); + PRINT_D(INIT_DBG, "Download Succeeded\n"); _FAIL_: return ret; } - /* startup configuration - could be changed later using iconfig*/ static int linux_wlan_init_test_config(struct net_device *dev, linux_wlan_t *p_nic) { @@ -1094,7 +1047,6 @@ static int linux_wlan_init_test_config(struct net_device *dev, linux_wlan_t *p_n PRINT_D(INIT_DBG, "MAC address is : %02x-%02x-%02x-%02x-%02x-%02x\n", mac_add[0], mac_add[1], mac_add[2], mac_add[3], mac_add[4], mac_add[5]); wilc_get_chipid(0); - if (g_linux_wlan->oup.wlan_cfg_set == NULL) { PRINT_D(INIT_DBG, "Null p[ointer\n"); goto _fail_; @@ -1114,7 +1066,6 @@ static int linux_wlan_init_test_config(struct net_device *dev, linux_wlan_t *p_n if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_BSS_TYPE, c_val, 1, 0, 0)) goto _fail_; - /* c_val[0] = RATE_AUTO; / * bug 4275: Enable autorate and limit it to 24Mbps * / */ c_val[0] = RATE_AUTO; if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_CURRENT_TX_RATE, c_val, 1, 0, 0)) @@ -1349,7 +1300,6 @@ _fail_: return -1; } - /**************************/ void wilc1000_wlan_deinit(linux_wlan_t *nic) { @@ -1383,16 +1333,12 @@ void wilc1000_wlan_deinit(linux_wlan_t *nic) #endif #endif - /* not sure if the following unlocks are needed or not*/ - if (&g_linux_wlan->rxq_event != NULL) { + if (&g_linux_wlan->rxq_event != NULL) linux_wlan_unlock(&g_linux_wlan->rxq_event); - } - if (&g_linux_wlan->txq_event != NULL) { + if (&g_linux_wlan->txq_event != NULL) linux_wlan_unlock(&g_linux_wlan->txq_event); - } - #if (RX_BH_TYPE == RX_BH_WORK_QUEUE) /*Removing the work struct from the linux kernel workqueue*/ @@ -1410,7 +1356,6 @@ void wilc1000_wlan_deinit(linux_wlan_t *nic) PRINT_D(INIT_DBG, "Deinitializing IRQ\n"); deinit_irq(g_linux_wlan); - if (&g_linux_wlan->oup != NULL) { if (g_linux_wlan->oup.wlan_stop != NULL) g_linux_wlan->oup.wlan_stop(); @@ -1534,7 +1479,7 @@ void linux_to_wlan(wilc_wlan_inp_t *nwi, linux_wlan_t *nic) nwi->os_context.txq_wait_event = (void *)&g_linux_wlan->txq_event; -#if defined (MEMORY_STATIC) +#if defined(MEMORY_STATIC) nwi->os_context.rx_buffer_size = LINUX_RX_SIZE; #endif nwi->os_context.rxq_critical_section = (void *)&g_linux_wlan->rxq_cs; @@ -1671,17 +1616,14 @@ static void wlan_deinitialize_threads(linux_wlan_t *nic) if (&g_linux_wlan->rxq_event != NULL) linux_wlan_unlock(&g_linux_wlan->rxq_event); - if (g_linux_wlan->rxq_thread != NULL) { kthread_stop(g_linux_wlan->rxq_thread); g_linux_wlan->rxq_thread = NULL; } - if (&g_linux_wlan->txq_event != NULL) linux_wlan_unlock(&g_linux_wlan->txq_event); - if (g_linux_wlan->txq_thread != NULL) { kthread_stop(g_linux_wlan->txq_thread); g_linux_wlan->txq_thread = NULL; @@ -1745,14 +1687,12 @@ static int linux_wlan_read_mac_addr(void *vp) } } - if (index == array_size) { + if (index == array_size) PRINT_ER("random MAC\n"); - } exit: - if (fp && !IS_ERR(fp)) { + if (fp && !IS_ERR(fp)) filp_close(fp, NULL); - } set_fs(old_fs); @@ -1784,9 +1724,8 @@ uint8_t wilc1000_prepare_11b_core(wilc_wlan_inp_t *nwi, wilc_wlan_oup_t *nwo, li sdio_register_driver(&wilc_bus); - while (!probe) { + while (!probe) msleep(100); - } probe = 0; g_linux_wlan->wilc_sdio_func = local_sdio_func; linux_to_wlan(nwi, nic); @@ -1818,9 +1757,8 @@ int repeat_power_cycle(perInterface_wlan_t *nic) sdio_register_driver(&wilc_bus); /* msleep(1000); */ - while (!probe) { + while (!probe) msleep(100); - } probe = 0; g_linux_wlan->wilc_sdio_func = local_sdio_func; linux_to_wlan(&nwi, g_linux_wlan); @@ -1832,7 +1770,7 @@ int repeat_power_cycle(perInterface_wlan_t *nic) #endif if (linux_wlan_get_firmware(nic)) { - PRINT_ER("Can't get firmware \n"); + PRINT_ER("Can't get firmware\n"); ret = -1; goto __fail__; } @@ -1845,9 +1783,8 @@ int repeat_power_cycle(perInterface_wlan_t *nic) } /* Start firmware*/ ret = linux_wlan_start_firmware(nic); - if (ret < 0) { + if (ret < 0) PRINT_ER("Failed to start firmware\n"); - } __fail__: return ret; } @@ -1869,9 +1806,8 @@ int wilc1000_wlan_init(struct net_device *dev, perInterface_wlan_t *p_nic) #ifdef STATIC_MACADDRESS wilc_mac_thread = kthread_run(linux_wlan_read_mac_addr, NULL, "wilc_mac_thread"); - if (wilc_mac_thread < 0) { + if (wilc_mac_thread < 0) PRINT_ER("couldn't create Mac addr thread\n"); - } #endif linux_to_wlan(&nwi, g_linux_wlan); @@ -1887,7 +1823,6 @@ int wilc1000_wlan_init(struct net_device *dev, perInterface_wlan_t *p_nic) /*Save the oup structre into global pointer*/ gpstrWlanOps = &g_linux_wlan->oup; - ret = wlan_initialize_threads(nic); if (ret < 0) { PRINT_ER("Initializing Threads FAILED\n"); @@ -1920,12 +1855,11 @@ int wilc1000_wlan_init(struct net_device *dev, perInterface_wlan_t *p_nic) #endif if (linux_wlan_get_firmware(nic)) { - PRINT_ER("Can't get firmware \n"); + PRINT_ER("Can't get firmware\n"); ret = -EIO; goto _fail_irq_enable_; } - /*Download firmware*/ ret = linux_wlan_firmware_download(g_linux_wlan); if (ret < 0) { @@ -1965,7 +1899,6 @@ int wilc1000_wlan_init(struct net_device *dev, perInterface_wlan_t *p_nic) g_linux_wlan->wilc1000_initialized = 1; return 0; /*success*/ - _fail_fw_start_: if (&g_linux_wlan->oup != NULL) { if (g_linux_wlan->oup.wlan_stop != NULL) @@ -1994,12 +1927,11 @@ _fail_locks_: return ret; } - /* * - this function will be called automatically by OS when module inserted. */ -#if !defined (NM73131_0_BOARD) +#if !defined(NM73131_0_BOARD) int mac_init_fn(struct net_device *ndev) { @@ -2026,12 +1958,11 @@ int mac_init_fn(struct net_device *ndev) } #endif - void WILC_WFI_frame_register(struct wiphy *wiphy, struct net_device *dev, u16 frame_type, bool reg); /* This fn is called, when this device is setup using ifconfig */ -#if !defined (NM73131_0_BOARD) +#if !defined(NM73131_0_BOARD) int mac_open(struct net_device *ndev) { perInterface_wlan_t *nic; @@ -2090,7 +2021,6 @@ int mac_open(struct net_device *ndev) goto _err_; } - WILC_WFI_frame_register(nic->wilc_netdev->ieee80211_ptr->wiphy, nic->wilc_netdev, nic->g_struct_frame_reg[0].frame_type, nic->g_struct_frame_reg[0].reg); WILC_WFI_frame_register(nic->wilc_netdev->ieee80211_ptr->wiphy, nic->wilc_netdev, @@ -2129,7 +2059,6 @@ struct net_device_stats *mac_stats(struct net_device *dev) { perInterface_wlan_t *nic = netdev_priv(dev); - return &nic->netstats; } @@ -2144,17 +2073,16 @@ static void wilc_set_multicast_list(struct net_device *dev) priv = wiphy_priv(dev->ieee80211_ptr->wiphy); pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv; - if (!dev) return; - PRINT_D(INIT_DBG, "Setting Multicast List with count = %d. \n", dev->mc.count); + PRINT_D(INIT_DBG, "Setting Multicast List with count = %d.\n", dev->mc.count); if (dev->flags & IFF_PROMISC) { /* Normally, we should configure the chip to retrive all packets * but we don't wanna support this right now */ /* TODO: add promiscuous mode support */ - PRINT_D(INIT_DBG, "Set promiscuous mode ON, retrive all packets \n"); + PRINT_D(INIT_DBG, "Set promiscuous mode ON, retrive all packets\n"); return; } @@ -2193,11 +2121,10 @@ static void linux_wlan_tx_complete(void *priv, int status) { struct tx_complete_data *pv_data = (struct tx_complete_data *)priv; - if (status == 1) { + if (status == 1) PRINT_D(TX_DBG, "Packet sent successfully - Size = %d - Address = %p - SKB = %p\n", pv_data->size, pv_data->buff, pv_data->skb); - } else { + else PRINT_D(TX_DBG, "Couldn't send packet - Size = %d - Address = %p - SKB = %p\n", pv_data->size, pv_data->buff, pv_data->skb); - } /* Free the SK Buffer, its work is done */ dev_kfree_skb(pv_data->skb); linux_wlan_free(pv_data); @@ -2213,7 +2140,7 @@ int mac_xmit(struct sk_buff *skb, struct net_device *ndev) struct ethhdr *eth_h; nic = netdev_priv(ndev); - PRINT_D(INT_DBG, "\n========\n IntUH: %d - IntBH: %d - IntCld: %d \n========\n", int_rcvdU, int_rcvdB, int_clrd); + PRINT_D(INT_DBG, "\n========\n IntUH: %d - IntBH: %d - IntCld: %d\n========\n", int_rcvdU, int_rcvdB, int_clrd); PRINT_D(TX_DBG, "Sending packet just received from TCP/IP\n"); /* Stop the network interface queue */ @@ -2235,18 +2162,16 @@ int mac_xmit(struct sk_buff *skb, struct net_device *ndev) tx_data->skb = skb; eth_h = (struct ethhdr *)(skb->data); - if (eth_h->h_proto == 0x8e88) { + if (eth_h->h_proto == 0x8e88) PRINT_D(INIT_DBG, "EAPOL transmitted\n"); - } /*get source and dest ip addresses*/ ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr)); pu8UdpBuffer = (char *)ih + sizeof(struct iphdr); - if ((pu8UdpBuffer[1] == 68 && pu8UdpBuffer[3] == 67) || (pu8UdpBuffer[1] == 67 && pu8UdpBuffer[3] == 68)) { + if ((pu8UdpBuffer[1] == 68 && pu8UdpBuffer[3] == 67) || (pu8UdpBuffer[1] == 67 && pu8UdpBuffer[3] == 68)) PRINT_D(GENERIC_DBG, "DHCP Message transmitted, type:%x %x %x\n", pu8UdpBuffer[248], pu8UdpBuffer[249], pu8UdpBuffer[250]); - } PRINT_D(TX_DBG, "Sending packet - Size = %d - Address = %p - SKB = %p\n", tx_data->size, tx_data->buff, tx_data->skb); /* Send packet to MAC HW - for now the tx_complete function will be just status @@ -2267,7 +2192,6 @@ int mac_xmit(struct sk_buff *skb, struct net_device *ndev) QueueCount = WILC_Xmit_data((void *)tx_data, HOST_TO_WLAN); #endif /* WILC_FULLY_HOSTING_AP */ - if (QueueCount > FLOW_CONTROL_UPPER_THRESHOLD) { netif_stop_queue(g_linux_wlan->strInterfaceInfo[0].wilc_netdev); netif_stop_queue(g_linux_wlan->strInterfaceInfo[1].wilc_netdev); @@ -2276,7 +2200,6 @@ int mac_xmit(struct sk_buff *skb, struct net_device *ndev) return 0; } - int mac_close(struct net_device *ndev) { struct WILC_WFI_priv *priv; @@ -2299,8 +2222,6 @@ int mac_close(struct net_device *ndev) pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv; - - PRINT_D(GENERIC_DBG, "Mac close\n"); if (g_linux_wlan == NULL) { @@ -2346,7 +2267,6 @@ int mac_close(struct net_device *ndev) return 0; } - int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd) { @@ -2357,8 +2277,6 @@ int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd) struct WILC_WFI_priv *priv; s32 s32Error = WILC_SUCCESS; - - /* struct iwreq *wrq = (struct iwreq *) req; // tony moved to case SIOCSIWPRIV */ #ifdef USE_WIRELESS nic = netdev_priv(ndev); @@ -2420,9 +2338,8 @@ int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd) done: - if (buff != NULL) { + if (buff != NULL) kfree(buff); - } return s32Error; } @@ -2453,7 +2370,6 @@ void frmw_to_linux(uint8_t *buff, uint32_t size, uint32_t pkt_offset) frame_len = size; buff_to_send = buff; - /* Need to send the packet up to the host, allocate a skb buffer */ skb = dev_alloc_skb(frame_len); if (skb == NULL) { @@ -2463,14 +2379,12 @@ void frmw_to_linux(uint8_t *buff, uint32_t size, uint32_t pkt_offset) skb_reserve(skb, (unsigned int)skb->data & 0x3); - if (g_linux_wlan == NULL || wilc_netdev == NULL) { + if (g_linux_wlan == NULL || wilc_netdev == NULL) PRINT_ER("wilc_netdev in g_linux_wlan is NULL"); - } skb->dev = wilc_netdev; - if (skb->dev == NULL) { + if (skb->dev == NULL) PRINT_ER("skb->dev is NULL\n"); - } /* * for(i=0;i<40;i++) @@ -2500,9 +2414,8 @@ void frmw_to_linux(uint8_t *buff, uint32_t size, uint32_t pkt_offset) ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr)); pu8UdpBuffer = (char *)ih + sizeof(struct iphdr); - if (buff_to_send[35] == 67 && buff_to_send[37] == 68) { + if (buff_to_send[35] == 67 && buff_to_send[37] == 68) PRINT_D(RX_DBG, "DHCP Message received\n"); - } if (buff_to_send[12] == 0x88 && buff_to_send[13] == 0x8e) PRINT_D(GENERIC_DBG, "eapol received\n"); #endif @@ -2514,9 +2427,8 @@ void frmw_to_linux(uint8_t *buff, uint32_t size, uint32_t pkt_offset) PRINT_D(RX_DBG, "netif_rx ret value is: %d\n", stats); } #ifndef TCP_ENHANCEMENTS - else { + else PRINT_ER("Discard sending packet with len = %d\n", size); - } #endif } @@ -2539,9 +2451,8 @@ void WILC_WFI_mgmt_rx(uint8_t *buff, uint32_t size) #ifdef WILC_P2P nic = netdev_priv(g_linux_wlan->strInterfaceInfo[1].wilc_netdev); /* p2p0 */ if ((buff[0] == nic->g_struct_frame_reg[0].frame_type && nic->g_struct_frame_reg[0].reg) || - (buff[0] == nic->g_struct_frame_reg[1].frame_type && nic->g_struct_frame_reg[1].reg)) { + (buff[0] == nic->g_struct_frame_reg[1].frame_type && nic->g_struct_frame_reg[1].reg)) WILC_WFI_p2p_rx(g_linux_wlan->strInterfaceInfo[1].wilc_netdev, buff, size); - } #endif } @@ -2623,7 +2534,6 @@ int wilc_netdev_init(void) } #endif - if (register_netdev(ndev)) { PRINT_ER("Device couldn't be registered - %s\n", ndev->name); return -1; /* ERROR */ @@ -2636,7 +2546,7 @@ int wilc_netdev_init(void) #ifndef WILC_SDIO if (!linux_spi_init(&g_linux_wlan->wilc_spidev)) { - PRINT_ER("Can't initialize SPI \n"); + PRINT_ER("Can't initialize SPI\n"); return -1; /* ERROR */ } g_linux_wlan->wilc_spidev = wilc_spi_dev; @@ -2647,13 +2557,10 @@ int wilc_netdev_init(void) return 0; } - /*The 1st function called after module inserted*/ static int __init init_wilc_driver(void) { - - -#if defined (WILC_DEBUGFS) +#if defined(WILC_DEBUGFS) if (wilc_debugfs_init() < 0) { PRINT_D(GENERIC_DBG, "fail to create debugfs for wilc driver\n"); return -1; @@ -2672,17 +2579,15 @@ static int __init init_wilc_driver(void) int ret; ret = sdio_register_driver(&wilc_bus); - if (ret < 0) { + if (ret < 0) PRINT_D(INIT_DBG, "init_wilc_driver: Failed register sdio driver\n"); - } return ret; } #else PRINT_D(INIT_DBG, "Initializing netdev\n"); - if (wilc_netdev_init()) { + if (wilc_netdev_init()) PRINT_ER("Couldn't initialize netdev\n"); - } return 0; #endif } @@ -2700,18 +2605,15 @@ static void __exit exit_wilc_driver(void) unregister_inetaddr_notifier(&g_dev_notifier); #endif - for (i = 0; i < NUM_CONCURRENT_IFC; i++) { + for (i = 0; i < NUM_CONCURRENT_IFC; i++) nic[i] = netdev_priv(g_linux_wlan->strInterfaceInfo[i].wilc_netdev); - } } - if ((g_linux_wlan != NULL) && g_linux_wlan->wilc_firmware != NULL) { release_firmware(g_linux_wlan->wilc_firmware); g_linux_wlan->wilc_firmware = NULL; } - if ((g_linux_wlan != NULL) && (((g_linux_wlan->strInterfaceInfo[0].wilc_netdev) != NULL) || ((g_linux_wlan->strInterfaceInfo[1].wilc_netdev) != NULL))) { PRINT_D(INIT_DBG, "Waiting for mac_close ....\n"); @@ -2721,17 +2623,15 @@ static void __exit exit_wilc_driver(void) else PRINT_D(INIT_DBG, "mac_closed\n"); - for (i = 0; i < NUM_CONCURRENT_IFC; i++) { /* close all opened interfaces */ if (g_linux_wlan->strInterfaceInfo[i].wilc_netdev != NULL) { - if (nic[i]->mac_opened) { + if (nic[i]->mac_opened) mac_close(g_linux_wlan->strInterfaceInfo[i].wilc_netdev); - } } } for (i = 0; i < NUM_CONCURRENT_IFC; i++) { - PRINT_D(INIT_DBG, "Unregistering netdev %p \n", g_linux_wlan->strInterfaceInfo[i].wilc_netdev); + PRINT_D(INIT_DBG, "Unregistering netdev %p\n", g_linux_wlan->strInterfaceInfo[i].wilc_netdev); unregister_netdev(g_linux_wlan->strInterfaceInfo[i].wilc_netdev); #ifdef USE_WIRELESS PRINT_D(INIT_DBG, "Freeing Wiphy...\n"); @@ -2742,7 +2642,6 @@ static void __exit exit_wilc_driver(void) } } - #ifdef USE_WIRELESS #ifdef WILC_AP_EXTERNAL_MLME /* Bug 4600 : WILC_WFI_deinit_mon_interface was already called at mac_close */ @@ -2767,7 +2666,7 @@ static void __exit exit_wilc_driver(void) } printk("Module_exit Done.\n"); -#if defined (WILC_DEBUGFS) +#if defined(WILC_DEBUGFS) wilc_debugfs_remove(); #endif @@ -2778,4 +2677,3 @@ static void __exit exit_wilc_driver(void) module_exit(exit_wilc_driver); MODULE_LICENSE("GPL"); -#endif diff --git a/drivers/staging/wilc1000/linux_wlan_sdio.c b/drivers/staging/wilc1000/linux_wlan_sdio.c index 858e3a191bce..37f31f4558b5 100644 --- a/drivers/staging/wilc1000/linux_wlan_sdio.c +++ b/drivers/staging/wilc1000/linux_wlan_sdio.c @@ -31,7 +31,6 @@ struct sdio_func *local_sdio_func; extern linux_wlan_t *g_linux_wlan; extern int wilc_netdev_init(void); -extern int sdio_clear_int(void); extern void wilc_handle_isr(void); static unsigned int sdio_default_speed; diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index c328208cda29..be2e901b448d 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -62,11 +62,10 @@ static ssize_t wilc_debug_level_write(struct file *filp, const char *buf, size_t flag = buffer[0] - '0'; - if (flag > 0) { + if (flag > 0) flag = DEBUG | ERR; - } else if (flag < 0) { + else if (flag < 0) flag = 100; - } if (flag > DBG_LEVEL_ALL) { printk("%s, value (0x%08x) is out of range, stay previous flag (0x%08x)\n", __func__, flag, atomic_read(&DEBUG_LEVEL)); @@ -75,11 +74,10 @@ static ssize_t wilc_debug_level_write(struct file *filp, const char *buf, size_t atomic_set(&DEBUG_LEVEL, (int)flag); - if (flag == 0) { + if (flag == 0) printk("Debug-level disabled\n"); - } else { + else printk("Debug-level enabled\n"); - } return count; } diff --git a/drivers/staging/wilc1000/wilc_memory.c b/drivers/staging/wilc1000/wilc_memory.c index c70707fefb66..34ef13e8e243 100644 --- a/drivers/staging/wilc1000/wilc_memory.c +++ b/drivers/staging/wilc1000/wilc_memory.c @@ -9,11 +9,10 @@ void *WILC_MemoryAlloc(u32 u32Size, tstrWILC_MemoryAttrs *strAttrs, char *pcFileName, u32 u32LineNo) { - if (u32Size > 0) { + if (u32Size > 0) return kmalloc(u32Size, GFP_ATOMIC); - } else { + else return NULL; - } } /*! diff --git a/drivers/staging/wilc1000/wilc_platform.h b/drivers/staging/wilc1000/wilc_platform.h index d03532cc3af2..ccceaae212a5 100644 --- a/drivers/staging/wilc1000/wilc_platform.h +++ b/drivers/staging/wilc1000/wilc_platform.h @@ -1,5 +1,5 @@ -#ifndef __WILC_platfrom_H__ -#define __WILC_platfrom_H__ +#ifndef __WILC_platform_H__ +#define __WILC_platform_H__ #include <linux/kthread.h> #include <linux/semaphore.h> diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c index 897e47e317ff..5a18148a593e 100644 --- a/drivers/staging/wilc1000/wilc_sdio.c +++ b/drivers/staging/wilc1000/wilc_sdio.c @@ -10,17 +10,7 @@ #include "wilc_wlan_if.h" #include "wilc_wlan.h" - -#ifdef WILC1000_SINGLE_TRANSFER -#define WILC_SDIO_BLOCK_SIZE 256 -#else - #if defined(PLAT_AML8726_M3) /* johnny */ - #define WILC_SDIO_BLOCK_SIZE 512 - #define MAX_SEG_SIZE (1 << 12) /* 4096 */ - #else - #define WILC_SDIO_BLOCK_SIZE 512 - #endif -#endif +#define WILC_SDIO_BLOCK_SIZE 512 typedef struct { void *os_context; @@ -90,7 +80,6 @@ static int sdio_set_func0_csa_address_byte0(uint32_t adr) { sdio_cmd52_t cmd; - /** * Review: BIG ENDIAN **/ @@ -108,6 +97,7 @@ static int sdio_set_func0_csa_address_byte0(uint32_t adr) _fail_: return 0; } + static int sdio_set_func0_block_size(uint32_t block_size) { sdio_cmd52_t cmd; @@ -170,6 +160,7 @@ static int sdio_clear_int(void) #ifndef WILC_SDIO_IRQ_GPIO /* uint32_t sts; */ sdio_cmd52_t cmd; + cmd.read_write = 0; cmd.function = 1; cmd.raw = 0; @@ -181,6 +172,7 @@ static int sdio_clear_int(void) return cmd.data; #else uint32_t reg; + if (!sdio_read_reg(WILC_HOST_RX_CTRL_0, ®)) { g_sdio.dPrint(N_ERR, "[wilc spi]: Failed read reg (%08x)...\n", WILC_HOST_RX_CTRL_0); return 0; @@ -197,6 +189,7 @@ uint32_t sdio_xfer_cnt(void) { uint32_t cnt = 0; sdio_cmd52_t cmd; + cmd.read_write = 0; cmd.function = 1; cmd.raw = 0; @@ -222,8 +215,6 @@ uint32_t sdio_xfer_cnt(void) cnt |= (cmd.data << 16); return cnt; - - } /******************************************** @@ -263,6 +254,7 @@ static int sdio_write_reg(uint32_t addr, uint32_t data) if ((addr >= 0xf0) && (addr <= 0xff)) { sdio_cmd52_t cmd; + cmd.read_write = 1; cmd.function = 0; cmd.raw = 0; @@ -325,16 +317,6 @@ static int sdio_write(uint32_t addr, uint8_t *buf, uint32_t size) cmd.function = 0; cmd.address = 0x10f; } else { -#ifdef WILC1000_SINGLE_TRANSFER - /** - * has to be block aligned... - **/ - nleft = size % block_size; - if (nleft > 0) { - size += block_size; - size &= ~(block_size - 1); - } -#else /** * has to be word aligned... **/ @@ -342,7 +324,6 @@ static int sdio_write(uint32_t addr, uint8_t *buf, uint32_t size) size += 4; size &= ~0x3; } -#endif /** * func 1 access @@ -355,89 +336,6 @@ static int sdio_write(uint32_t addr, uint8_t *buf, uint32_t size) nleft = size % block_size; if (nblk > 0) { - -#if defined(PLAT_AML8726_M3_BACKUP) /* johnny */ - int i; - - for (i = 0; i < nblk; i++) { - cmd.block_mode = 0; /* 1; */ - cmd.increment = 1; - cmd.count = block_size; /* nblk; */ - cmd.buffer = buf; - cmd.block_size = block_size; - if (addr > 0) { - if (!sdio_set_func0_csa_address(addr)) - goto _fail_; - } - if (!g_sdio.sdio_cmd53(&cmd)) { - g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block send...\n", addr); - goto _fail_; - } - - if (addr > 0) - addr += block_size; /* addr += nblk*block_size; */ - - buf += block_size; /* buf += nblk*block_size; */ - } - -#elif defined(PLAT_AML8726_M3) /* johnny */ - - int i; - int rest; - int seg_cnt; - - seg_cnt = (nblk * block_size) / MAX_SEG_SIZE; - rest = (nblk * block_size) & (MAX_SEG_SIZE - 1); - - for (i = 0; i < seg_cnt; i++) { - cmd.block_mode = 1; - cmd.increment = 1; - cmd.count = MAX_SEG_SIZE / block_size; - cmd.buffer = buf; - cmd.block_size = block_size; - - if (addr > 0) { - if (!sdio_set_func0_csa_address(addr)) - goto _fail_; - } - if (!g_sdio.sdio_cmd53(&cmd)) { - g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block send...\n", addr); - goto _fail_; - } - - if (addr > 0) - addr += MAX_SEG_SIZE; - - buf += MAX_SEG_SIZE; - - } - - - if (rest > 0) { - cmd.block_mode = 1; - cmd.increment = 1; - cmd.count = rest / block_size; - cmd.buffer = buf; - cmd.block_size = block_size; /* johnny : prevent it from setting unexpected value */ - - if (addr > 0) { - if (!sdio_set_func0_csa_address(addr)) - goto _fail_; - } - if (!g_sdio.sdio_cmd53(&cmd)) { - g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], bytes send...\n", addr); - goto _fail_; - } - - if (addr > 0) - addr += rest; - - buf += rest; - - } - -#else - cmd.block_mode = 1; cmd.increment = 1; cmd.count = nblk; @@ -454,11 +352,8 @@ static int sdio_write(uint32_t addr, uint8_t *buf, uint32_t size) if (addr > 0) addr += nblk * block_size; buf += nblk * block_size; - -#endif /* platform */ } - if (nleft > 0) { cmd.block_mode = 0; cmd.increment = 1; @@ -488,6 +383,7 @@ static int sdio_read_reg(uint32_t addr, uint32_t *data) { if ((addr >= 0xf0) && (addr <= 0xff)) { sdio_cmd52_t cmd; + cmd.read_write = 0; cmd.function = 0; cmd.raw = 0; @@ -552,16 +448,6 @@ static int sdio_read(uint32_t addr, uint8_t *buf, uint32_t size) cmd.function = 0; cmd.address = 0x10f; } else { -#ifdef WILC1000_SINGLE_TRANSFER - /** - * has to be block aligned... - **/ - nleft = size % block_size; - if (nleft > 0) { - size += block_size; - size &= ~(block_size - 1); - } -#else /** * has to be word aligned... **/ @@ -569,7 +455,6 @@ static int sdio_read(uint32_t addr, uint8_t *buf, uint32_t size) size += 4; size &= ~0x3; } -#endif /** * func 1 access @@ -582,89 +467,6 @@ static int sdio_read(uint32_t addr, uint8_t *buf, uint32_t size) nleft = size % block_size; if (nblk > 0) { - -#if defined(PLAT_AML8726_M3_BACKUP) /* johnny */ - - int i; - - for (i = 0; i < nblk; i++) { - cmd.block_mode = 0; /* 1; */ - cmd.increment = 1; - cmd.count = block_size; /* nblk; */ - cmd.buffer = buf; - cmd.block_size = block_size; - if (addr > 0) { - if (!sdio_set_func0_csa_address(addr)) - goto _fail_; - } - if (!g_sdio.sdio_cmd53(&cmd)) { - g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block read...\n", addr); - goto _fail_; - } - if (addr > 0) - addr += block_size; /* addr += nblk*block_size; */ - buf += block_size; /* buf += nblk*block_size; */ - } - -#elif defined(PLAT_AML8726_M3) /* johnny */ - - int i; - int rest; - int seg_cnt; - - seg_cnt = (nblk * block_size) / MAX_SEG_SIZE; - rest = (nblk * block_size) & (MAX_SEG_SIZE - 1); - - for (i = 0; i < seg_cnt; i++) { - cmd.block_mode = 1; - cmd.increment = 1; - cmd.count = MAX_SEG_SIZE / block_size; - cmd.buffer = buf; - cmd.block_size = block_size; - - - if (addr > 0) { - if (!sdio_set_func0_csa_address(addr)) - goto _fail_; - } - if (!g_sdio.sdio_cmd53(&cmd)) { - g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block read...\n", addr); - goto _fail_; - } - - if (addr > 0) - addr += MAX_SEG_SIZE; - - buf += MAX_SEG_SIZE; - - } - - - if (rest > 0) { - cmd.block_mode = 1; - cmd.increment = 1; - cmd.count = rest / block_size; - cmd.buffer = buf; - cmd.block_size = block_size; /* johnny : prevent it from setting unexpected value */ - - if (addr > 0) { - if (!sdio_set_func0_csa_address(addr)) - goto _fail_; - } - if (!g_sdio.sdio_cmd53(&cmd)) { - g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block read...\n", addr); - goto _fail_; - } - - if (addr > 0) - addr += rest; - - buf += rest; - - } - -#else - cmd.block_mode = 1; cmd.increment = 1; cmd.count = nblk; @@ -681,8 +483,6 @@ static int sdio_read(uint32_t addr, uint8_t *buf, uint32_t size) if (addr > 0) addr += nblk * block_size; buf += nblk * block_size; - -#endif /* platform */ } /* if (nblk > 0) */ if (nleft > 0) { @@ -784,6 +584,7 @@ static int sdio_init(wilc_wlan_inp_t *inp, wilc_debug_func func) sdio_cmd52_t cmd; int loop; uint32_t chipid; + memset(&g_sdio, 0, sizeof(wilc_sdio_t)); g_sdio.dPrint = func; @@ -891,14 +692,12 @@ static int sdio_init(wilc_wlan_inp_t *inp, wilc_debug_func func) goto _fail_; } g_sdio.dPrint(N_ERR, "[wilc sdio]: chipid (%08x)\n", chipid); - if ((chipid & 0xfff) > 0x2a0) { + if ((chipid & 0xfff) > 0x2a0) g_sdio.has_thrpt_enh3 = 1; - } else { + else g_sdio.has_thrpt_enh3 = 0; - } g_sdio.dPrint(N_ERR, "[wilc sdio]: has_thrpt_enh3 = %d...\n", g_sdio.has_thrpt_enh3); - return 1; _fail_: @@ -925,23 +724,21 @@ static int sdio_read_size(uint32_t *size) /** * Read DMA count in words **/ - { - cmd.read_write = 0; - cmd.function = 0; - cmd.raw = 0; - cmd.address = 0xf2; - cmd.data = 0; - g_sdio.sdio_cmd52(&cmd); - tmp = cmd.data; + cmd.read_write = 0; + cmd.function = 0; + cmd.raw = 0; + cmd.address = 0xf2; + cmd.data = 0; + g_sdio.sdio_cmd52(&cmd); + tmp = cmd.data; - /* cmd.read_write = 0; */ - /* cmd.function = 0; */ - /* cmd.raw = 0; */ - cmd.address = 0xf3; - cmd.data = 0; - g_sdio.sdio_cmd52(&cmd); - tmp |= (cmd.data << 8); - } + /* cmd.read_write = 0; */ + /* cmd.function = 0; */ + /* cmd.raw = 0; */ + cmd.address = 0xf3; + cmd.data = 0; + g_sdio.sdio_cmd52(&cmd); + tmp |= (cmd.data << 8); *size = tmp; return 1; @@ -966,26 +763,21 @@ static int sdio_read_int(uint32_t *int_status) cmd.data = 0; g_sdio.sdio_cmd52(&cmd); - if (cmd.data & (1 << 0)) { + if (cmd.data & (1 << 0)) tmp |= INT_0; - } - if (cmd.data & (1 << 2)) { + if (cmd.data & (1 << 2)) tmp |= INT_1; - } - if (cmd.data & (1 << 3)) { + if (cmd.data & (1 << 3)) tmp |= INT_2; - } - if (cmd.data & (1 << 4)) { + if (cmd.data & (1 << 4)) tmp |= INT_3; - } - if (cmd.data & (1 << 5)) { + if (cmd.data & (1 << 5)) tmp |= INT_4; - } - if (cmd.data & (1 << 6)) { + if (cmd.data & (1 << 6)) tmp |= INT_5; - } { int i; + for (i = g_sdio.nint; i < MAX_NUM_INT; i++) { if ((tmp >> (IRG_FLAGS_OFFSET + i)) & 0x1) { g_sdio.dPrint(N_ERR, "[wilc sdio]: Unexpected interrupt (1) : tmp=%x, data=%x\n", tmp, cmd.data); @@ -1024,6 +816,7 @@ static int sdio_clear_int_ext(uint32_t val) #ifdef WILC_SDIO_IRQ_GPIO { uint32_t flags; + flags = val & ((1 << MAX_NUN_INT_THRPT_ENH2) - 1); reg = flags; } @@ -1041,6 +834,7 @@ static int sdio_clear_int_ext(uint32_t val) reg |= (1 << 7); if (reg) { sdio_cmd52_t cmd; + cmd.read_write = 1; cmd.function = 0; cmd.raw = 0; @@ -1060,6 +854,7 @@ static int sdio_clear_int_ext(uint32_t val) /* see below. has_thrpt_enh2 uses register 0xf8 to clear interrupts. */ /* Cannot clear multiple interrupts. Must clear each interrupt individually */ uint32_t flags; + flags = val & ((1 << MAX_NUM_INT) - 1); if (flags) { int i; @@ -1068,6 +863,7 @@ static int sdio_clear_int_ext(uint32_t val) for (i = 0; i < g_sdio.nint; i++) { if (flags & 1) { sdio_cmd52_t cmd; + cmd.read_write = 1; cmd.function = 0; cmd.raw = 0; @@ -1085,9 +881,8 @@ static int sdio_clear_int_ext(uint32_t val) break; flags >>= 1; } - if (!ret) { + if (!ret) goto _fail_; - } for (i = g_sdio.nint; i < MAX_NUM_INT; i++) { if (flags & 1) g_sdio.dPrint(N_ERR, "[wilc sdio]: Unexpected interrupt cleared %d...\n", i); @@ -1097,7 +892,6 @@ static int sdio_clear_int_ext(uint32_t val) } #endif /* WILC_SDIO_IRQ_GPIO */ - { uint32_t vmm_ctl; @@ -1138,7 +932,6 @@ static int sdio_sync_ext(int nint /* how mant interrupts to enable. */) { uint32_t reg; - if (nint > MAX_NUM_INT) { g_sdio.dPrint(N_ERR, "[wilc sdio]: Too many interupts (%d)...\n", nint); return 0; @@ -1148,7 +941,6 @@ static int sdio_sync_ext(int nint /* how mant interrupts to enable. */) return 0; } - g_sdio.nint = nint; /** @@ -1170,7 +962,6 @@ static int sdio_sync_ext(int nint /* how mant interrupts to enable. */) uint32_t reg; int ret, i; - /** * interrupt pin mux select **/ @@ -1195,9 +986,8 @@ static int sdio_sync_ext(int nint /* how mant interrupts to enable. */) return 0; } - for (i = 0; (i < 5) && (nint > 0); i++, nint--) { + for (i = 0; (i < 5) && (nint > 0); i++, nint--) reg |= (1 << (27 + i)); - } ret = sdio_write_reg(WILC_INTR_ENABLE, reg); if (!ret) { g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write reg (%08x)...\n", WILC_INTR_ENABLE); @@ -1210,9 +1000,8 @@ static int sdio_sync_ext(int nint /* how mant interrupts to enable. */) return 0; } - for (i = 0; (i < 3) && (nint > 0); i++, nint--) { + for (i = 0; (i < 3) && (nint > 0); i++, nint--) reg |= (1 << i); - } ret = sdio_read_reg(WILC_INTR2_ENABLE, ®); if (!ret) { @@ -1225,7 +1014,6 @@ static int sdio_sync_ext(int nint /* how mant interrupts to enable. */) return 1; } - /******************************************** * * Global sdio HIF function table diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c index abea5df656d7..1bf7d314ae34 100644 --- a/drivers/staging/wilc1000/wilc_spi.c +++ b/drivers/staging/wilc1000/wilc_spi.c @@ -374,11 +374,10 @@ static int spi_cmd_complete(uint8_t cmd, uint32_t adr, uint8_t *b, uint32_t sz, return result; } - if (!g_spi.crc_off) { + if (!g_spi.crc_off) wb[len - 1] = (crc7(0x7f, (const uint8_t *)&wb[0], len - 1)) << 1; - } else { + else len -= 1; - } #define NUM_SKIP_BYTES (1) #define NUM_RSP_BYTES (2) @@ -522,11 +521,10 @@ static int spi_cmd_complete(uint8_t cmd, uint32_t adr, uint8_t *b, uint32_t sz, if (sz > 0) { int nbytes; - if (sz <= (DATA_PKT_SZ - ix)) { + if (sz <= (DATA_PKT_SZ - ix)) nbytes = sz; - } else { + else nbytes = DATA_PKT_SZ - ix; - } /** * Read bytes @@ -557,11 +555,10 @@ static int spi_cmd_complete(uint8_t cmd, uint32_t adr, uint8_t *b, uint32_t sz, while (sz > 0) { int nbytes; - if (sz <= DATA_PKT_SZ) { + if (sz <= DATA_PKT_SZ) nbytes = sz; - } else { + else nbytes = DATA_PKT_SZ; - } /** * read data response only on the next DMA cycles not diff --git a/drivers/staging/wilc1000/wilc_strutils.c b/drivers/staging/wilc1000/wilc_strutils.c index e0145953ceef..a32b9c13e872 100644 --- a/drivers/staging/wilc1000/wilc_strutils.c +++ b/drivers/staging/wilc1000/wilc_strutils.c @@ -4,15 +4,6 @@ #include "wilc_strutils.h" -/*! - * @author syounan - * @date 18 Aug 2010 - * @version 1.0 - */ -s32 WILC_memcmp(const void *pvArg1, const void *pvArg2, u32 u32Count) -{ - return memcmp(pvArg1, pvArg2, u32Count); -} /*! @@ -25,15 +16,6 @@ void WILC_memcpy_INTERNAL(void *pvTarget, const void *pvSource, u32 u32Count) memcpy(pvTarget, pvSource, u32Count); } -/*! - * @author syounan - * @date 18 Aug 2010 - * @version 1.0 - */ -void *WILC_memset(void *pvTarget, u8 u8SetValue, u32 u32Count) -{ - return memset(pvTarget, u8SetValue, u32Count); -} /*! * @author syounan @@ -59,11 +41,10 @@ s32 WILC_strncmp(const char *pcStr1, const char *pcStr2, s32Result = 1; } else { s32Result = strncmp(pcStr1, pcStr2, u32Count); - if (s32Result < 0) { + if (s32Result < 0) s32Result = -1; - } else if (s32Result > 0) { + else if (s32Result > 0) s32Result = 1; - } } return s32Result; diff --git a/drivers/staging/wilc1000/wilc_strutils.h b/drivers/staging/wilc1000/wilc_strutils.h index d1445575a25e..9e3c5d9c5001 100644 --- a/drivers/staging/wilc1000/wilc_strutils.h +++ b/drivers/staging/wilc1000/wilc_strutils.h @@ -14,19 +14,6 @@ #include <linux/string.h> #include "wilc_errorsupport.h" -/*! - * @brief Compares two memory buffers - * @param[in] pvArg1 pointer to the first memory location - * @param[in] pvArg2 pointer to the second memory location - * @param[in] u32Count the size of the memory buffers - * @return 0 if the 2 buffers are equal, 1 if pvArg1 is bigger than pvArg2, - * -1 if pvArg1 smaller than pvArg2 - * @note this function repeats the functionality of standard memcmp - * @author syounan - * @date 18 Aug 2010 - * @version 1.0 - */ -s32 WILC_memcmp(const void *pvArg1, const void *pvArg2, u32 u32Count); /*! * @brief Internal implementation for memory copy @@ -71,18 +58,6 @@ static WILC_ErrNo WILC_memcpy(void *pvTarget, const void *pvSource, u32 u32Count } } -/*! - * @brief Sets the contents of a memory buffer with the given value - * @param[in] pvTarget the target buffer which contsnts will be set - * @param[in] u8SetValue the value to be used - * @param[in] u32Count the size of the memory buffer - * @return value of pvTarget - * @note this function repeats the functionality of standard memset - * @author syounan - * @date 18 Aug 2010 - * @version 1.0 - */ -void *WILC_memset(void *pvTarget, u8 u8SetValue, u32 u32Count); /*! * @brief copies the contents of source string into the target string diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 1d0b7f87b100..5c459679aa5a 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -22,7 +22,6 @@ #define IS_MGMT_STATUS_SUCCES 0x040 #define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff) -extern void linux_wlan_free(void *vp); extern int linux_wlan_get_firmware(perInterface_wlan_t *p_nic); extern void linux_wlan_unlock(void *vp); extern u16 Set_machw_change_vir_if(bool bValue); @@ -112,7 +111,7 @@ u8 u8P2P_oui[] = {0x50, 0x6f, 0x9A, 0x09}; u8 u8P2Plocalrandom = 0x01; u8 u8P2Precvrandom = 0x00; u8 u8P2P_vendorspec[] = {0xdd, 0x05, 0x00, 0x08, 0x40, 0x03}; -bool bWilc_ie = false; +bool bWilc_ie; #endif static struct ieee80211_supported_band WILC_WFI_band_2ghz = { @@ -135,9 +134,9 @@ struct add_key_params g_add_ptk_key_params; struct wilc_wfi_key g_key_ptk_params; struct wilc_wfi_wep_key g_key_wep_params; u8 g_flushing_in_progress; -bool g_ptk_keys_saved = false; -bool g_gtk_keys_saved = false; -bool g_wep_keys_saved = false; +bool g_ptk_keys_saved; +bool g_gtk_keys_saved; +bool g_wep_keys_saved; #define AGING_TIME (9 * 1000) #define duringIP_TIME 15000 @@ -202,7 +201,7 @@ void refresh_scan(void *pUserVoid, uint8_t all, bool bDirectScan) channel = ieee80211_get_channel(wiphy, s32Freq); rssi = get_rssi_avg(pstrNetworkInfo); - if (WILC_memcmp("DIRECT-", pstrNetworkInfo->au8ssid, 7) || bDirectScan) { + if (memcmp("DIRECT-", pstrNetworkInfo->au8ssid, 7) || bDirectScan) { bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, pstrNetworkInfo->au8bssid, pstrNetworkInfo->u64Tsf, pstrNetworkInfo->u16CapInfo, pstrNetworkInfo->u16BeaconPeriod, (const u8 *)pstrNetworkInfo->pu8IEs, (size_t)pstrNetworkInfo->u16IEsLen, (((s32)rssi) * 100), GFP_KERNEL); @@ -240,7 +239,7 @@ void remove_network_from_shadow(void *pUserVoid) for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) { if (time_after(now, astrLastScannedNtwrksShadow[i].u32TimeRcvdInScan + (unsigned long)(SCAN_RESULT_EXPIRE))) { - PRINT_D(CFG80211_DBG, "Network expired in ScanShadow: %s \n", astrLastScannedNtwrksShadow[i].au8ssid); + PRINT_D(CFG80211_DBG, "Network expired in ScanShadow: %s\n", astrLastScannedNtwrksShadow[i].au8ssid); if (astrLastScannedNtwrksShadow[i].pu8IEs != NULL) { WILC_FREE(astrLastScannedNtwrksShadow[i].pu8IEs); @@ -283,7 +282,7 @@ int8_t is_network_in_shadow(tstrNetworkInfo *pstrNetworkInfo, void *pUserVoid) } else { /* Linear search for now */ for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) { - if (WILC_memcmp(astrLastScannedNtwrksShadow[i].au8bssid, + if (memcmp(astrLastScannedNtwrksShadow[i].au8bssid, pstrNetworkInfo->au8bssid, 6) == 0) { state = i; break; @@ -394,7 +393,7 @@ static void CfgScanResult(tenuScanEvent enuScanEvent, tstrNetworkInfo *pstrNetwo WILC_NULLCHECK(s32Error, channel); PRINT_INFO(CFG80211_DBG, "Network Info:: CHANNEL Frequency: %d, RSSI: %d, CapabilityInfo: %d," - "BeaconPeriod: %d \n", channel->center_freq, (((s32)pstrNetworkInfo->s8rssi) * 100), + "BeaconPeriod: %d\n", channel->center_freq, (((s32)pstrNetworkInfo->s8rssi) * 100), pstrNetworkInfo->u16CapInfo, pstrNetworkInfo->u16BeaconPeriod); if (pstrNetworkInfo->bNewNetwork == true) { @@ -414,7 +413,7 @@ static void CfgScanResult(tenuScanEvent enuScanEvent, tstrNetworkInfo *pstrNetwo /*P2P peers are sent to WPA supplicant and added to shadow table*/ - if (!(WILC_memcmp("DIRECT-", pstrNetworkInfo->au8ssid, 7))) { + if (!(memcmp("DIRECT-", pstrNetworkInfo->au8ssid, 7))) { bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, pstrNetworkInfo->au8bssid, pstrNetworkInfo->u64Tsf, pstrNetworkInfo->u16CapInfo, pstrNetworkInfo->u16BeaconPeriod, (const u8 *)pstrNetworkInfo->pu8IEs, (size_t)pstrNetworkInfo->u16IEsLen, (((s32)pstrNetworkInfo->s8rssi) * 100), GFP_KERNEL); @@ -429,8 +428,8 @@ static void CfgScanResult(tenuScanEvent enuScanEvent, tstrNetworkInfo *pstrNetwo u32 i; /* So this network is discovered before, we'll just update its RSSI */ for (i = 0; i < priv->u32RcvdChCount; i++) { - if (WILC_memcmp(astrLastScannedNtwrksShadow[i].au8bssid, pstrNetworkInfo->au8bssid, 6) == 0) { - PRINT_D(CFG80211_DBG, "Update RSSI of %s \n", astrLastScannedNtwrksShadow[i].au8ssid); + if (memcmp(astrLastScannedNtwrksShadow[i].au8bssid, pstrNetworkInfo->au8bssid, 6) == 0) { + PRINT_D(CFG80211_DBG, "Update RSSI of %s\n", astrLastScannedNtwrksShadow[i].au8ssid); astrLastScannedNtwrksShadow[i].s8rssi = pstrNetworkInfo->s8rssi; astrLastScannedNtwrksShadow[i].u32TimeRcvdInScan = jiffies; @@ -440,15 +439,14 @@ static void CfgScanResult(tenuScanEvent enuScanEvent, tstrNetworkInfo *pstrNetwo } } } else if (enuScanEvent == SCAN_EVENT_DONE) { - PRINT_D(CFG80211_DBG, "Scan Done[%p] \n", priv->dev); - PRINT_D(CFG80211_DBG, "Refreshing Scan ... \n"); + PRINT_D(CFG80211_DBG, "Scan Done[%p]\n", priv->dev); + PRINT_D(CFG80211_DBG, "Refreshing Scan ...\n"); refresh_scan(priv, 1, false); - if (priv->u32RcvdChCount > 0) { - PRINT_D(CFG80211_DBG, "%d Network(s) found \n", priv->u32RcvdChCount); - } else { - PRINT_D(CFG80211_DBG, "No networks found \n"); - } + if (priv->u32RcvdChCount > 0) + PRINT_D(CFG80211_DBG, "%d Network(s) found\n", priv->u32RcvdChCount); + else + PRINT_D(CFG80211_DBG, "No networks found\n"); down(&(priv->hSemScanReq)); @@ -465,7 +463,7 @@ static void CfgScanResult(tenuScanEvent enuScanEvent, tstrNetworkInfo *pstrNetwo else if (enuScanEvent == SCAN_EVENT_ABORTED) { down(&(priv->hSemScanReq)); - PRINT_D(CFG80211_DBG, "Scan Aborted \n"); + PRINT_D(CFG80211_DBG, "Scan Aborted\n"); if (priv->pstrScanReq != NULL) { update_scan_time(priv); @@ -503,7 +501,7 @@ int WILC_WFI_Set_PMKSA(u8 *bssid, struct WILC_WFI_priv *priv) for (i = 0; i < priv->pmkid_list.numpmkid; i++) { - if (!WILC_memcmp(bssid, priv->pmkid_list.pmkidlist[i].bssid, + if (!memcmp(bssid, priv->pmkid_list.pmkidlist[i].bssid, ETH_ALEN)) { PRINT_D(CFG80211_DBG, "PMKID successful comparison"); @@ -574,7 +572,7 @@ static void CfgConnectResult(tenuConnDisconnEvent enuConnDisconnEvent, * = SUCCESSFUL_STATUSCODE, while mac status is MAC_DISCONNECTED (which means something wrong happened) */ u16ConnectStatus = WLAN_STATUS_UNSPECIFIED_FAILURE; linux_wlan_set_bssid(priv->dev, NullBssid); - WILC_memset(u8ConnectedSSID, 0, ETH_ALEN); + memset(u8ConnectedSSID, 0, ETH_ALEN); /*BugID_5457*/ /*Invalidate u8WLANChannel value on wlan0 disconnect*/ @@ -583,7 +581,7 @@ static void CfgConnectResult(tenuConnDisconnEvent enuConnDisconnEvent, u8WLANChannel = INVALID_CHANNEL; #endif - PRINT_ER("Unspecified failure: Connection status %d : MAC status = %d \n", u16ConnectStatus, u8MacStatus); + PRINT_ER("Unspecified failure: Connection status %d : MAC status = %d\n", u16ConnectStatus, u8MacStatus); } if (u16ConnectStatus == WLAN_STATUS_SUCCESS) { @@ -599,7 +597,7 @@ static void CfgConnectResult(tenuConnDisconnEvent enuConnDisconnEvent, * Linux kernel warning generated at the nl80211 layer */ for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) { - if (WILC_memcmp(astrLastScannedNtwrksShadow[i].au8bssid, + if (memcmp(astrLastScannedNtwrksShadow[i].au8bssid, pstrConnectInfo->au8bssid, ETH_ALEN) == 0) { unsigned long now = jiffies; @@ -640,9 +638,9 @@ static void CfgConnectResult(tenuConnDisconnEvent enuConnDisconnEvent, u8P2Plocalrandom = 0x01; u8P2Precvrandom = 0x00; bWilc_ie = false; - WILC_memset(priv->au8AssociatedBss, 0, ETH_ALEN); + memset(priv->au8AssociatedBss, 0, ETH_ALEN); linux_wlan_set_bssid(priv->dev, NullBssid); - WILC_memset(u8ConnectedSSID, 0, ETH_ALEN); + memset(u8ConnectedSSID, 0, ETH_ALEN); /*BugID_5457*/ /*Invalidate u8WLANChannel value on wlan0 disconnect*/ @@ -769,17 +767,17 @@ static int WILC_WFI_CfgScan(struct wiphy *wiphy, struct cfg80211_scan_request *r WILC_memcpy(strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid, request->ssids[i].ssid, request->ssids[i].ssid_len); strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen = request->ssids[i].ssid_len; } else { - PRINT_D(CFG80211_DBG, "Received one NULL SSID \n"); + PRINT_D(CFG80211_DBG, "Received one NULL SSID\n"); strHiddenNetwork.u8ssidnum -= 1; } } - PRINT_D(CFG80211_DBG, "Trigger Scan Request \n"); + PRINT_D(CFG80211_DBG, "Trigger Scan Request\n"); s32Error = host_int_scan(priv->hWILCWFIDrv, USER_SCAN, ACTIVE_SCAN, au8ScanChanList, request->n_channels, (const u8 *)request->ie, request->ie_len, CfgScanResult, (void *)priv, &strHiddenNetwork); } else { - PRINT_D(CFG80211_DBG, "Trigger Scan Request \n"); + PRINT_D(CFG80211_DBG, "Trigger Scan Request\n"); s32Error = host_int_scan(priv->hWILCWFIDrv, USER_SCAN, ACTIVE_SCAN, au8ScanChanList, request->n_channels, (const u8 *)request->ie, request->ie_len, @@ -788,7 +786,7 @@ static int WILC_WFI_CfgScan(struct wiphy *wiphy, struct cfg80211_scan_request *r } else { PRINT_ER("Requested num of scanned channels is greater than the max, supported" - " channels \n"); + " channels\n"); } if (s32Error != WILC_SUCCESS) { @@ -841,11 +839,11 @@ static int WILC_WFI_CfgConnect(struct wiphy *wiphy, struct net_device *dev, } else pstrWFIDrv->u8P2PConnect = 0; #endif - PRINT_INFO(CFG80211_DBG, "Required SSID = %s\n , AuthType = %d \n", sme->ssid, sme->auth_type); + PRINT_INFO(CFG80211_DBG, "Required SSID = %s\n , AuthType = %d\n", sme->ssid, sme->auth_type); for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) { if ((sme->ssid_len == astrLastScannedNtwrksShadow[i].u8SsidLen) && - WILC_memcmp(astrLastScannedNtwrksShadow[i].au8ssid, + memcmp(astrLastScannedNtwrksShadow[i].au8ssid, sme->ssid, sme->ssid_len) == 0) { PRINT_INFO(CFG80211_DBG, "Network with required SSID is found %s\n", sme->ssid); @@ -857,7 +855,7 @@ static int WILC_WFI_CfgConnect(struct wiphy *wiphy, struct net_device *dev, } else { /* BSSID is also passed from the user, so decision of matching * should consider also this passed BSSID */ - if (WILC_memcmp(astrLastScannedNtwrksShadow[i].au8bssid, + if (memcmp(astrLastScannedNtwrksShadow[i].au8bssid, sme->bssid, ETH_ALEN) == 0) { PRINT_INFO(CFG80211_DBG, "BSSID is passed from the user and matched\n"); @@ -887,8 +885,8 @@ static int WILC_WFI_CfgConnect(struct wiphy *wiphy, struct net_device *dev, } priv->WILC_WFI_wep_default = 0; - WILC_memset(priv->WILC_WFI_wep_key, 0, sizeof(priv->WILC_WFI_wep_key)); - WILC_memset(priv->WILC_WFI_wep_key_len, 0, sizeof(priv->WILC_WFI_wep_key_len)); + memset(priv->WILC_WFI_wep_key, 0, sizeof(priv->WILC_WFI_wep_key)); + memset(priv->WILC_WFI_wep_key_len, 0, sizeof(priv->WILC_WFI_wep_key_len)); PRINT_INFO(CFG80211_DBG, "sme->crypto.wpa_versions=%x\n", sme->crypto.wpa_versions); PRINT_INFO(CFG80211_DBG, "sme->crypto.cipher_group=%x\n", sme->crypto.cipher_group); @@ -1046,7 +1044,7 @@ static int WILC_WFI_CfgConnect(struct wiphy *wiphy, struct net_device *dev, tenuAuth_type, pstrNetworkInfo->u8channel, pstrNetworkInfo->pJoinParams); if (s32Error != WILC_SUCCESS) { - PRINT_ER("host_int_set_join_req(): Error(%d) \n", s32Error); + PRINT_ER("host_int_set_join_req(): Error(%d)\n", s32Error); s32Error = -ENOENT; goto done; } @@ -1170,7 +1168,7 @@ static int WILC_WFI_add_key(struct wiphy *wiphy, struct net_device *netdev, u8 k break; } #endif - if (WILC_memcmp(params->key, priv->WILC_WFI_wep_key[key_index], params->key_len)) { + if (memcmp(params->key, priv->WILC_WFI_wep_key[key_index], params->key_len)) { priv->WILC_WFI_wep_default = key_index; priv->WILC_WFI_wep_key_len[key_index] = params->key_len; WILC_memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len); @@ -1205,8 +1203,7 @@ static int WILC_WFI_add_key(struct wiphy *wiphy, struct net_device *netdev, u8 k - if (!pairwise) - { + if (!pairwise) { if (params->cipher == WLAN_CIPHER_SUITE_TKIP) u8gmode = ENCRYPT_ENABLED | WPA | TKIP; else @@ -1304,8 +1301,7 @@ static int WILC_WFI_add_key(struct wiphy *wiphy, struct net_device *netdev, u8 k { u8mode = 0; - if (!pairwise) - { + if (!pairwise) { if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) { /* swap the tx mic by rx mic */ pu8RxMic = params->key + 24; @@ -1492,7 +1488,7 @@ static int WILC_WFI_del_key(struct wiphy *wiphy, struct net_device *netdev, } if (key_index >= 0 && key_index <= 3) { - WILC_memset(priv->WILC_WFI_wep_key[key_index], 0, priv->WILC_WFI_wep_key_len[key_index]); + memset(priv->WILC_WFI_wep_key[key_index], 0, priv->WILC_WFI_wep_key_len[key_index]); priv->WILC_WFI_wep_key_len[key_index] = 0; PRINT_D(CFG80211_DBG, "Removing WEP key with index = %d\n", key_index); @@ -1577,7 +1573,7 @@ static int WILC_WFI_set_default_key(struct wiphy *wiphy, struct net_device *netd priv = wiphy_priv(wiphy); - PRINT_D(CFG80211_DBG, "Setting default key with idx = %d \n", key_index); + PRINT_D(CFG80211_DBG, "Setting default key with idx = %d\n", key_index); if (key_index != priv->WILC_WFI_wep_default) { @@ -1622,7 +1618,6 @@ static int WILC_WFI_dump_survey(struct wiphy *wiphy, struct net_device *netdev, * @version 1.0 */ -extern uint32_t Statisitcs_totalAcks, Statisitcs_DroppedAcks; static int WILC_WFI_get_station(struct wiphy *wiphy, struct net_device *dev, const u8 *mac, struct station_info *sinfo) { @@ -1678,7 +1673,7 @@ static int WILC_WFI_get_station(struct wiphy *wiphy, struct net_device *dev, * kernel version 3.0.0 */ sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL) | - BIT( NL80211_STA_INFO_RX_PACKETS) | + BIT(NL80211_STA_INFO_RX_PACKETS) | BIT(NL80211_STA_INFO_TX_PACKETS) | BIT(NL80211_STA_INFO_TX_FAILED) | BIT(NL80211_STA_INFO_TX_BITRATE); @@ -1690,11 +1685,10 @@ static int WILC_WFI_get_station(struct wiphy *wiphy, struct net_device *dev, sinfo->txrate.legacy = strStatistics.u8LinkSpeed * 10; #ifdef TCP_ENHANCEMENTS - if ((strStatistics.u8LinkSpeed > TCP_ACK_FILTER_LINK_SPEED_THRESH) && (strStatistics.u8LinkSpeed != DEFAULT_LINK_SPEED)) { + if ((strStatistics.u8LinkSpeed > TCP_ACK_FILTER_LINK_SPEED_THRESH) && (strStatistics.u8LinkSpeed != DEFAULT_LINK_SPEED)) Enable_TCP_ACK_Filter(true); - } else if (strStatistics.u8LinkSpeed != DEFAULT_LINK_SPEED) { + else if (strStatistics.u8LinkSpeed != DEFAULT_LINK_SPEED) Enable_TCP_ACK_Filter(false); - } #endif PRINT_D(CORECONFIG_DBG, "*** stats[%d][%d][%d][%d][%d]\n", sinfo->signal, sinfo->rx_packets, sinfo->tx_packets, @@ -1815,7 +1809,7 @@ static int WILC_WFI_set_wiphy_params(struct wiphy *wiphy, u32 changed) priv = wiphy_priv(wiphy); pstrCfgParamVal.u32SetCfgFlag = 0; - PRINT_D(CFG80211_DBG, "Setting Wiphy params \n"); + PRINT_D(CFG80211_DBG, "Setting Wiphy params\n"); if (changed & WIPHY_PARAM_RETRY_SHORT) { PRINT_D(CFG80211_DBG, "Setting WIPHY_PARAM_RETRY_SHORT %d\n", @@ -1898,7 +1892,7 @@ static int WILC_WFI_set_pmksa(struct wiphy *wiphy, struct net_device *netdev, for (i = 0; i < priv->pmkid_list.numpmkid; i++) { - if (!WILC_memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid, + if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid, ETH_ALEN)) { /*If bssid already exists and pmkid value needs to reset*/ flag = PMKID_FOUND; @@ -1948,11 +1942,11 @@ static int WILC_WFI_del_pmksa(struct wiphy *wiphy, struct net_device *netdev, PRINT_D(CFG80211_DBG, "Deleting PMKSA keys\n"); for (i = 0; i < priv->pmkid_list.numpmkid; i++) { - if (!WILC_memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid, + if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid, ETH_ALEN)) { /*If bssid is found, reset the values*/ PRINT_D(CFG80211_DBG, "Reseting PMKID values\n"); - WILC_memset(&priv->pmkid_list.pmkidlist[i], 0, sizeof(tstrHostIFpmkid)); + memset(&priv->pmkid_list.pmkidlist[i], 0, sizeof(tstrHostIFpmkid)); flag = PMKID_FOUND; break; } @@ -1991,7 +1985,7 @@ static int WILC_WFI_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) PRINT_D(CFG80211_DBG, "Flushing PMKID key values\n"); /*Get cashed Pmkids and set all with zeros*/ - WILC_memset(&priv->pmkid_list, 0, sizeof(tstrHostIFpmkidAttr)); + memset(&priv->pmkid_list, 0, sizeof(tstrHostIFpmkidAttr)); return 0; } @@ -2063,11 +2057,10 @@ void WILC_WFI_CfgParseRxAction(u8 *buf, u32 len) } #endif /* USE_SUPPLICANT_GO_INTENT */ - if (buf[index] == CHANLIST_ATTR_ID) { + if (buf[index] == CHANLIST_ATTR_ID) channel_list_attr_index = index; - } else if (buf[index] == OPERCHAN_ATTR_ID) { + else if (buf[index] == OPERCHAN_ATTR_ID) op_channel_attr_index = index; - } index += buf[index + 1] + 3; /* ID,Length byte */ } @@ -2149,11 +2142,10 @@ void WILC_WFI_CfgParseTxAction(u8 *buf, u32 len, bool bOperChan, u8 iftype) } #endif - if (buf[index] == CHANLIST_ATTR_ID) { + if (buf[index] == CHANLIST_ATTR_ID) channel_list_attr_index = index; - } else if (buf[index] == OPERCHAN_ATTR_ID) { + else if (buf[index] == OPERCHAN_ATTR_ID) op_channel_attr_index = index; - } index += buf[index + 1] + 3; /* ID,Length byte */ } @@ -2259,11 +2251,11 @@ void WILC_WFI_p2p_rx (struct net_device *dev, uint8_t *buff, uint32_t size) case PUBLIC_ACT_VENDORSPEC: /*Now we have a public action vendor specific action frame, check if its a p2p public action frame * based on the standard its should have the p2p_oui attribute with the following values 50 6f 9A 09*/ - if (!WILC_memcmp(u8P2P_oui, &buff[ACTION_SUBTYPE_ID + 1], 4)) { + if (!memcmp(u8P2P_oui, &buff[ACTION_SUBTYPE_ID + 1], 4)) { if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP)) { if (!bWilc_ie) { for (i = P2P_PUB_ACTION_SUBTYPE; i < size; i++) { - if (!WILC_memcmp(u8P2P_vendorspec, &buff[i], 6)) { + if (!memcmp(u8P2P_vendorspec, &buff[i], 6)) { u8P2Precvrandom = buff[i + 6]; bWilc_ie = true; PRINT_D(GENERIC_DBG, "WILC Vendor specific IE:%02x\n", u8P2Precvrandom); @@ -2276,7 +2268,7 @@ void WILC_WFI_p2p_rx (struct net_device *dev, uint8_t *buff, uint32_t size) if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP || buff[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)) { for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < size; i++) { - if (buff[i] == P2PELEM_ATTR_ID && !(WILC_memcmp(u8P2P_oui, &buff[i + 2], 4))) { + if (buff[i] == P2PELEM_ATTR_ID && !(memcmp(u8P2P_oui, &buff[i + 2], 4))) { WILC_WFI_CfgParseRxAction(&buff[i + 6], size - (i + 6)); break; } @@ -2340,7 +2332,7 @@ static void WILC_WFI_RemainOnChannelReady(void *pUserVoid) struct WILC_WFI_priv *priv; priv = (struct WILC_WFI_priv *)pUserVoid; - PRINT_D(HOSTINF_DBG, "Remain on channel ready \n"); + PRINT_D(HOSTINF_DBG, "Remain on channel ready\n"); priv->bInP2PlistenState = true; @@ -2368,7 +2360,7 @@ static void WILC_WFI_RemainOnChannelExpired(void *pUserVoid, u32 u32SessionID) /*BugID_5477*/ if (u32SessionID == priv->strRemainOnChanParams.u32ListenSessionID) { - PRINT_D(GENERIC_DBG, "Remain on channel expired \n"); + PRINT_D(GENERIC_DBG, "Remain on channel expired\n"); priv->bInP2PlistenState = false; @@ -2572,7 +2564,7 @@ int WILC_WFI_mgmt_tx(struct wiphy *wiphy, { /*Now we have a public action vendor specific action frame, check if its a p2p public action frame * based on the standard its should have the p2p_oui attribute with the following values 50 6f 9A 09*/ - if (!WILC_memcmp(u8P2P_oui, &buf[ACTION_SUBTYPE_ID + 1], 4)) { + if (!memcmp(u8P2P_oui, &buf[ACTION_SUBTYPE_ID + 1], 4)) { /*For the connection of two WILC's connection generate a rand number to determine who will be a GO*/ if ((buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP)) { if (u8P2Plocalrandom == 1 && u8P2Precvrandom < u8P2Plocalrandom) { @@ -2589,7 +2581,7 @@ int WILC_WFI_mgmt_tx(struct wiphy *wiphy, /*Search for the p2p information information element , after the Public action subtype theres a byte for teh dialog token, skip that*/ for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < len; i++) { - if (buf[i] == P2PELEM_ATTR_ID && !(WILC_memcmp(u8P2P_oui, &buf[i + 2], 4))) { + if (buf[i] == P2PELEM_ATTR_ID && !(memcmp(u8P2P_oui, &buf[i + 2], 4))) { if (buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP) WILC_WFI_CfgParseTxAction(&mgmt_tx->buff[i + 6], len - (i + 6), true, nic->iftype); @@ -2875,7 +2867,6 @@ static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev /*Remove the enteries of the previously connected clients*/ memset(priv->assoc_stainfo.au8Sta_AssociatedBss, 0, MAX_NUM_STA * ETH_ALEN); - #ifndef SIMULATION #ifdef WILC_P2P interface_type = nic->iftype; nic->iftype = STATION_MODE; @@ -2953,7 +2944,6 @@ static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev host_int_set_power_mgmt(priv->hWILCWFIDrv, 1, 0); } #endif - #endif break; case NL80211_IFTYPE_P2P_CLIENT: @@ -2968,7 +2958,6 @@ static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev priv->wdev->iftype = type; nic->monitor_flag = 0; - #ifndef SIMULATION #ifdef WILC_P2P PRINT_D(HOSTAPD_DBG, "Downloading P2P_CONCURRENCY_FIRMWARE\n"); @@ -3042,7 +3031,6 @@ static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev } } #endif - #endif break; case NL80211_IFTYPE_AP: @@ -3053,7 +3041,6 @@ static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev nic->iftype = AP_MODE; PRINT_D(CORECONFIG_DBG, "priv->hWILCWFIDrv[%p]\n", priv->hWILCWFIDrv); - #ifndef SIMULATION PRINT_D(HOSTAPD_DBG, "Downloading AP firmware\n"); linux_wlan_get_firmware(nic); #ifdef WILC_P2P @@ -3075,7 +3062,6 @@ static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev } } #endif - #endif break; case NL80211_IFTYPE_P2P_GO: @@ -3099,7 +3085,6 @@ static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev PRINT_D(CORECONFIG_DBG, "priv->hWILCWFIDrv[%p]\n", priv->hWILCWFIDrv); - #ifndef SIMULATION #ifdef WILC_P2P PRINT_D(HOSTAPD_DBG, "Downloading P2P_CONCURRENCY_FIRMWARE\n"); @@ -3174,7 +3159,6 @@ static int WILC_WFI_change_virt_intf(struct wiphy *wiphy, struct net_device *dev } } #endif - #endif break; default: @@ -3223,7 +3207,7 @@ static int WILC_WFI_start_ap(struct wiphy *wiphy, struct net_device *dev, priv = wiphy_priv(wiphy); PRINT_D(HOSTAPD_DBG, "Starting ap\n"); - PRINT_D(HOSTAPD_DBG, "Interval = %d \n DTIM period = %d\n Head length = %zu Tail length = %zu\n", + PRINT_D(HOSTAPD_DBG, "Interval = %d\n DTIM period = %d\n Head length = %zu Tail length = %zu\n", settings->beacon_interval, settings->dtim_period, beacon->head_len, beacon->tail_len); s32Error = WILC_WFI_CfgSetChannel(wiphy, &settings->chandef); @@ -3342,7 +3326,7 @@ static int WILC_WFI_add_station(struct wiphy *wiphy, struct net_device *dev, { s32 s32Error = WILC_SUCCESS; struct WILC_WFI_priv *priv; - tstrWILC_AddStaParam strStaParams = {{0}}; + tstrWILC_AddStaParam strStaParams = { {0} }; perInterface_wlan_t *nic; @@ -3439,7 +3423,7 @@ static int WILC_WFI_del_station(struct wiphy *wiphy, struct net_device *dev, if (mac == NULL) { - PRINT_D(HOSTAPD_DBG, "All associated stations \n"); + PRINT_D(HOSTAPD_DBG, "All associated stations\n"); s32Error = host_int_del_allstation(priv->hWILCWFIDrv, priv->assoc_stainfo.au8Sta_AssociatedBss); } else { PRINT_D(HOSTAPD_DBG, "With mac address: %x%x%x%x%x%x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); @@ -3473,7 +3457,7 @@ static int WILC_WFI_change_station(struct wiphy *wiphy, struct net_device *dev, { s32 s32Error = WILC_SUCCESS; struct WILC_WFI_priv *priv; - tstrWILC_AddStaParam strStaParams = {{0}}; + tstrWILC_AddStaParam strStaParams = { {0} }; perInterface_wlan_t *nic; @@ -3570,13 +3554,8 @@ struct wireless_dev *WILC_WFI_add_virt_intf(struct wiphy *wiphy, const char *nam new_ifc = WILC_WFI_init_mon_interface(name, nic->wilc_netdev); if (new_ifc != NULL) { PRINT_D(HOSTAPD_DBG, "Setting monitor flag in private structure\n"); - #ifdef SIMULATION - priv = netdev_priv(priv->wdev->netdev); - priv->monitor_flag = 1; - #else nic = netdev_priv(priv->wdev->netdev); nic->monitor_flag = 1; - #endif } else PRINT_ER("Error in initializing monitor interface\n "); } diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.c b/drivers/staging/wilc1000/wilc_wfi_netdevice.c deleted file mode 100644 index af9b85822ced..000000000000 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.c +++ /dev/null @@ -1,909 +0,0 @@ -/*! - * @file wilc_wfi_netdevice.c - * @brief File Operations OS wrapper functionality - * @author mdaftedar - * @sa wilc_wfi_netdevice.h - * @date 01 MAR 2012 - * @version 1.0 - */ - -#ifdef SIMULATION - -#include "wilc_wfi_cfgoperations.h" -#include "host_interface.h" - -MODULE_AUTHOR("Mai Daftedar"); -MODULE_LICENSE("Dual BSD/GPL"); - -struct net_device *WILC_WFI_devs[2]; - -/* - * Transmitter lockup simulation, normally disabled. - */ -static int lockup; -module_param(lockup, int, 0); - -static int timeout = WILC_WFI_TIMEOUT; -module_param(timeout, int, 0); - -/* - * Do we run in NAPI mode? - */ -static int use_napi; -module_param(use_napi, int, 0); - -/* - * A structure representing an in-flight packet. - */ -struct WILC_WFI_packet { - struct WILC_WFI_packet *next; - struct net_device *dev; - int datalen; - u8 data[ETH_DATA_LEN]; -}; - -int pool_size = 8; -module_param(pool_size, int, 0); - -static void WILC_WFI_TxTimeout(struct net_device *dev); -static void (*WILC_WFI_Interrupt)(int, void *, struct pt_regs *); - -/** - * @brief WILC_WFI_SetupPool - * @details Set up a device's packet pool. - * @param[in] struct net_device *dev : Network Device Pointer - * @return NONE - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -void WILC_WFI_SetupPool(struct net_device *dev) -{ - struct WILC_WFI_priv *priv = netdev_priv(dev); - int i; - struct WILC_WFI_packet *pkt; - - priv->ppool = NULL; - for (i = 0; i < pool_size; i++) { - pkt = kmalloc(sizeof(struct WILC_WFI_packet), GFP_KERNEL); - if (pkt == NULL) { - PRINT_D(RX_DBG, "Ran out of memory allocating packet pool\n"); - return; - } - pkt->dev = dev; - pkt->next = priv->ppool; - priv->ppool = pkt; - } -} - -/** - * @brief WILC_WFI_TearDownPool - * @details Internal cleanup function that's called after the network device - * driver is unregistered - * @param[in] struct net_device *dev : Network Device Driver - * @return NONE - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -void WILC_WFI_TearDownPool(struct net_device *dev) -{ - struct WILC_WFI_priv *priv = netdev_priv(dev); - struct WILC_WFI_packet *pkt; - - while ((pkt = priv->ppool)) { - priv->ppool = pkt->next; - kfree(pkt); - /* FIXME - in-flight packets ? */ - } -} - -/** - * @brief WILC_WFI_GetTxBuffer - * @details Buffer/pool management - * @param[in] net_device *dev : Network Device Driver Structure - * @return struct WILC_WFI_packet - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -struct WILC_WFI_packet *WILC_WFI_GetTxBuffer(struct net_device *dev) -{ - struct WILC_WFI_priv *priv = netdev_priv(dev); - unsigned long flags; - struct WILC_WFI_packet *pkt; - - spin_lock_irqsave(&priv->lock, flags); - pkt = priv->ppool; - priv->ppool = pkt->next; - if (priv->ppool == NULL) { - PRINT_INFO(RX_DBG, "Pool empty\n"); - netif_stop_queue(dev); - } - spin_unlock_irqrestore(&priv->lock, flags); - return pkt; -} -/** - * @brief WILC_WFI_ReleaseBuffer - * @details Buffer/pool management - * @param[in] WILC_WFI_packet *pkt : Structure holding in-flight packet - * @return NONE - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -void WILC_WFI_ReleaseBuffer(struct WILC_WFI_packet *pkt) -{ - unsigned long flags; - struct WILC_WFI_priv *priv = netdev_priv(pkt->dev); - - spin_lock_irqsave(&priv->lock, flags); - pkt->next = priv->ppool; - priv->ppool = pkt; - spin_unlock_irqrestore(&priv->lock, flags); - if (netif_queue_stopped(pkt->dev) && pkt->next == NULL) - netif_wake_queue(pkt->dev); -} - -/** - * @brief WILC_WFI_EnqueueBuf - * @details Enqueuing packets in an RX buffer queue - * @param[in] WILC_WFI_packet *pkt : Structure holding in-flight packet - * @param[in] net_device *dev : Network Device Driver Structure - * @return NONE - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -void WILC_WFI_EnqueueBuf(struct net_device *dev, struct WILC_WFI_packet *pkt) -{ - unsigned long flags; - struct WILC_WFI_priv *priv = netdev_priv(dev); - - spin_lock_irqsave(&priv->lock, flags); - pkt->next = priv->rx_queue; /* FIXME - misorders packets */ - priv->rx_queue = pkt; - spin_unlock_irqrestore(&priv->lock, flags); -} - -/** - * @brief WILC_WFI_DequeueBuf - * @details Dequeuing packets from the RX buffer queue - * @param[in] net_device *dev : Network Device Driver Structure - * @return WILC_WFI_packet *pkt : Structure holding in-flight pac - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -struct WILC_WFI_packet *WILC_WFI_DequeueBuf(struct net_device *dev) -{ - struct WILC_WFI_priv *priv = netdev_priv(dev); - struct WILC_WFI_packet *pkt; - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - pkt = priv->rx_queue; - if (pkt != NULL) - priv->rx_queue = pkt->next; - spin_unlock_irqrestore(&priv->lock, flags); - return pkt; -} -/** - * @brief WILC_WFI_RxInts - * @details Enable and disable receive interrupts. - * @param[in] net_device *dev : Network Device Driver Structure - * @param[in] enable : Enable/Disable flag - * @return NONE - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -static void WILC_WFI_RxInts(struct net_device *dev, int enable) -{ - struct WILC_WFI_priv *priv = netdev_priv(dev); - - priv->rx_int_enabled = enable; -} - -/** - * @brief WILC_WFI_Open - * @details Open Network Device Driver, called when the network - * interface is opened. It starts the interface's transmit queue. - * @param[in] net_device *dev : Network Device Driver Structure - * @param[in] enable : Enable/Disable flag - * @return int : Returns 0 upon success. - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -int WILC_WFI_Open(struct net_device *dev) -{ - /* request_region(), request_irq(), .... (like fops->open) */ - /* - * Assign the hardware address of the board: use "\0SNULx", where - * x is 0 or 1. The first byte is '\0' to avoid being a multicast - * address (the first byte of multicast addrs is odd). - */ - memcpy(dev->dev_addr, "\0WLAN0", ETH_ALEN); - if (dev == WILC_WFI_devs[1]) - dev->dev_addr[ETH_ALEN - 1]++; /* \0SNUL1 */ - - WILC_WFI_InitHostInt(dev); - netif_start_queue(dev); - return 0; -} -/** - * @brief WILC_WFI_Release - * @details Release Network Device Driver, called when the network - * interface is stopped or brought down. This function marks - * the network driver as not being able to transmit - * @param[in] net_device *dev : Network Device Driver Structure - * @return int : Return 0 on Success. - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -int WILC_WFI_Release(struct net_device *dev) -{ - /* release ports, irq and such -- like fops->close */ - netif_stop_queue(dev); /* can't transmit any more */ - - return 0; -} -/** - * @brief WILC_WFI_Config - * @details Configuration changes (passed on by ifconfig) - * @param[in] net_device *dev : Network Device Driver Structure - * @param[in] struct ifmap *map : Contains the ioctl implementation for the - * network driver. - * @return int : Return 0 on Success. - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -int WILC_WFI_Config(struct net_device *dev, struct ifmap *map) -{ - if (dev->flags & IFF_UP) /* can't act on a running interface */ - return -EBUSY; - - /* Don't allow changing the I/O address */ - if (map->base_addr != dev->base_addr) { - PRINT_D(RX_DBG, KERN_WARNING "WILC_WFI: Can't change I/O address\n"); - return -EOPNOTSUPP; - } - - /* Allow changing the IRQ */ - if (map->irq != dev->irq) { - dev->irq = map->irq; - /* request_irq() is delayed to open-time */ - } - - /* ignore other fields */ - return 0; -} -/** - * @brief WILC_WFI_Rx - * @details Receive a packet: retrieve, encapsulate and pass over to upper - * levels - * @param[in] net_device *dev : Network Device Driver Structure - * @param[in] WILC_WFI_packet : - * @return NONE - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -void WILC_WFI_Rx(struct net_device *dev, struct WILC_WFI_packet *pkt) -{ - int i; - struct sk_buff *skb; - struct WILC_WFI_priv *priv = netdev_priv(dev); - s8 rssi; - /* - * The packet has been retrieved from the transmission - * medium. Build an skb around it, so upper layers can handle it - */ - - - skb = dev_alloc_skb(pkt->datalen + 2); - if (!skb) { - if (printk_ratelimit()) - PRINT_D(RX_DBG, "WILC_WFI rx: low on mem - packet dropped\n"); - priv->stats.rx_dropped++; - goto out; - } - skb_reserve(skb, 2); /* align IP on 16B boundary */ - memcpy(skb_put(skb, pkt->datalen), pkt->data, pkt->datalen); - - if (priv->monitor_flag) { - PRINT_INFO(RX_DBG, "In monitor device name %s\n", dev->name); - priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy); - PRINT_D(RX_DBG, "VALUE PASSED IN OF HRWD %p\n", priv->hWILCWFIDrv); - if (INFO) { - for (i = 14; i < skb->len; i++) - PRINT_INFO(RX_DBG, "RXdata[%d] %02x\n", i, skb->data[i]); - } - WILC_WFI_monitor_rx(dev, skb); - return; - } -out: - return; -} - -/** - * @brief WILC_WFI_Poll - * @details The poll implementation - * @param[in] struct napi_struct *napi : - * @param[in] int budget : - * @return int : Return 0 on Success. - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -static int WILC_WFI_Poll(struct napi_struct *napi, int budget) -{ - int npackets = 0; - struct sk_buff *skb; - struct WILC_WFI_priv *priv = container_of(napi, struct WILC_WFI_priv, napi); - struct net_device *dev = priv->dev; - struct WILC_WFI_packet *pkt; - - while (npackets < budget && priv->rx_queue) { - pkt = WILC_WFI_DequeueBuf(dev); - skb = dev_alloc_skb(pkt->datalen + 2); - if (!skb) { - if (printk_ratelimit()) - PRINT_D(RX_DBG, "WILC_WFI: packet dropped\n"); - priv->stats.rx_dropped++; - WILC_WFI_ReleaseBuffer(pkt); - continue; - } - skb_reserve(skb, 2); /* align IP on 16B boundary */ - memcpy(skb_put(skb, pkt->datalen), pkt->data, pkt->datalen); - skb->dev = dev; - skb->protocol = eth_type_trans(skb, dev); - skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */ - netif_receive_skb(skb); - /* Maintain stats */ - npackets++; - WILC_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy, pkt->datalen, WILC_WFI_RX_PKT); - WILC_WFI_ReleaseBuffer(pkt); - } - /* If we processed all packets, we're done; tell the kernel and re-enable ints */ - if (npackets < budget) { - napi_complete(napi); - WILC_WFI_RxInts(dev, 1); - } - return npackets; -} - -/** - * @brief WILC_WFI_Poll - * @details The typical interrupt entry point - * @param[in] struct napi_struct *napi : - * @param[in] int budget : - * @return int : Return 0 on Success. - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -static void WILC_WFI_RegularInterrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - int statusword; - struct WILC_WFI_priv *priv; - struct WILC_WFI_packet *pkt = NULL; - /* - * As usual, check the "device" pointer to be sure it is - * really interrupting. - * Then assign "struct device *dev" - */ - struct net_device *dev = (struct net_device *)dev_id; - /* ... and check with hw if it's really ours */ - - /* paranoid */ - if (!dev) - return; - - /* Lock the device */ - priv = netdev_priv(dev); - spin_lock(&priv->lock); - - /* retrieve statusword: real netdevices use I/O instructions */ - statusword = priv->status; - priv->status = 0; - if (statusword & WILC_WFI_RX_INTR) { - /* send it to WILC_WFI_rx for handling */ - pkt = priv->rx_queue; - if (pkt) { - priv->rx_queue = pkt->next; - WILC_WFI_Rx(dev, pkt); - } - } - if (statusword & WILC_WFI_TX_INTR) { - /* a transmission is over: free the skb */ - WILC_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy, priv->tx_packetlen, WILC_WFI_TX_PKT); - dev_kfree_skb(priv->skb); - } - - /* Unlock the device and we are done */ - spin_unlock(&priv->lock); - if (pkt) - WILC_WFI_ReleaseBuffer(pkt); /* Do this outside the lock! */ - return; -} -/** - * @brief WILC_WFI_NapiInterrupt - * @details A NAPI interrupt handler - * @param[in] irq: - * @param[in] dev_id: - * @param[in] pt_regs: - * @return NONE - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -static void WILC_WFI_NapiInterrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - int statusword; - struct WILC_WFI_priv *priv; - - /* - * As usual, check the "device" pointer for shared handlers. - * Then assign "struct device *dev" - */ - struct net_device *dev = (struct net_device *)dev_id; - /* ... and check with hw if it's really ours */ - - /* paranoid */ - if (!dev) - return; - - /* Lock the device */ - priv = netdev_priv(dev); - spin_lock(&priv->lock); - - /* retrieve statusword: real netdevices use I/O instructions */ - statusword = priv->status; - priv->status = 0; - if (statusword & WILC_WFI_RX_INTR) { - WILC_WFI_RxInts(dev, 0); /* Disable further interrupts */ - napi_schedule(&priv->napi); - } - if (statusword & WILC_WFI_TX_INTR) { - /* a transmission is over: free the skb */ - - WILC_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy, priv->tx_packetlen, WILC_WFI_TX_PKT); - dev_kfree_skb(priv->skb); - } - - /* Unlock the device and we are done */ - spin_unlock(&priv->lock); - return; -} - -/** - * @brief MI_WFI_HwTx - * @details Transmit a packet (low level interface) - * @param[in] buf: - * @param[in] len: - * @param[in] net_device *dev: - * @return NONE - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -void WILC_WFI_HwTx(char *buf, int len, struct net_device *dev) -{ - /* - * This function deals with hw details. This interface loops - * back the packet to the other WILC_WFI interface (if any). - * In other words, this function implements the WILC_WFI behaviour, - * while all other procedures are rather device-independent - */ - struct iphdr *ih; - struct net_device *dest; - struct WILC_WFI_priv *priv; - u32 *saddr, *daddr; - struct WILC_WFI_packet *tx_buffer; - - /* I am paranoid. Ain't I? */ - if (len < sizeof(struct ethhdr) + sizeof(struct iphdr)) { - PRINT_D(RX_DBG, "WILC_WFI: Hmm... packet too short (%i octets)\n", - len); - return; - } - - if (0) { /* enable this conditional to look at the data */ - int i; - - PRINT_D(RX_DBG, "len is %i", len); - for (i = 14; i < len; i++) - PRINT_D(RX_DBG, "TXdata[%d] %02x\n", i, buf[i] & 0xff); - /* PRINT_D(RX_DBG, "\n"); */ - } - /* - * Ethhdr is 14 bytes, but the kernel arranges for iphdr - * to be aligned (i.e., ethhdr is unaligned) - */ - ih = (struct iphdr *)(buf + sizeof(struct ethhdr)); - saddr = &ih->saddr; - daddr = &ih->daddr; - - ((u8 *)saddr)[2] ^= 1; /* change the third octet (class C) */ - ((u8 *)daddr)[2] ^= 1; - - ih->check = 0; /* and rebuild the checksum (ip needs it) */ - ih->check = ip_fast_csum((unsigned char *)ih, ih->ihl); - - - if (dev == WILC_WFI_devs[0]) - PRINT_D(RX_DBG, "%08x:%05i --> %08x:%05i\n", - ntohl(ih->saddr), ntohs(((struct tcphdr *)(ih + 1))->source), - ntohl(ih->daddr), ntohs(((struct tcphdr *)(ih + 1))->dest)); - else - PRINT_D(RX_DBG, "%08x:%05i <-- %08x:%05i\n", - ntohl(ih->daddr), ntohs(((struct tcphdr *)(ih + 1))->dest), - ntohl(ih->saddr), ntohs(((struct tcphdr *)(ih + 1))->source)); - - /* - * Ok, now the packet is ready for transmission: first simulate a - * receive interrupt on the twin device, then a - * transmission-done on the transmitting device - */ - dest = WILC_WFI_devs[dev == WILC_WFI_devs[0] ? 1 : 0]; - priv = netdev_priv(dest); - - tx_buffer = WILC_WFI_GetTxBuffer(dev); - tx_buffer->datalen = len; - memcpy(tx_buffer->data, buf, len); - WILC_WFI_EnqueueBuf(dest, tx_buffer); - if (priv->rx_int_enabled) { - priv->status |= WILC_WFI_RX_INTR; - WILC_WFI_Interrupt(0, dest, NULL); - } - - priv = netdev_priv(dev); - priv->tx_packetlen = len; - priv->tx_packetdata = buf; - priv->status |= WILC_WFI_TX_INTR; - if (lockup && ((priv->stats.tx_packets + 1) % lockup) == 0) { - /* Simulate a dropped transmit interrupt */ - netif_stop_queue(dev); - PRINT_D(RX_DBG, "Simulate lockup at %ld, txp %ld\n", jiffies, - (unsigned long) priv->stats.tx_packets); - } else - WILC_WFI_Interrupt(0, dev, NULL); -} - -/** - * @brief WILC_WFI_Tx - * @details Transmit a packet (called by the kernel) - * @param[in] sk_buff *skb: - * @param[in] net_device *dev: - * @return NONE - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -int WILC_WFI_Tx(struct sk_buff *skb, struct net_device *dev) -{ - int len; - char *data, shortpkt[ETH_ZLEN]; - struct WILC_WFI_priv *priv = netdev_priv(dev); - - data = skb->data; - len = skb->len; - - if (len < ETH_ZLEN) { - memset(shortpkt, 0, ETH_ZLEN); - memcpy(shortpkt, skb->data, skb->len); - len = ETH_ZLEN; - data = shortpkt; - } - dev->trans_start = jiffies; /* save the timestamp */ - - /* Remember the skb, so we can free it at interrupt time */ - priv->skb = skb; - - /* actual deliver of data is device-specific, and not shown here */ - WILC_WFI_HwTx(data, len, dev); - - return 0; /* Our simple device can not fail */ -} - -/** - * @brief WILC_WFI_TxTimeout - * @details Deal with a transmit timeout. - * @param[in] net_device *dev: - * @return NONE - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -void WILC_WFI_TxTimeout(struct net_device *dev) -{ - struct WILC_WFI_priv *priv = netdev_priv(dev); - - PRINT_D(RX_DBG, "Transmit timeout at %ld, latency %ld\n", jiffies, - jiffies - dev->trans_start); - /* Simulate a transmission interrupt to get things moving */ - priv->status = WILC_WFI_TX_INTR; - WILC_WFI_Interrupt(0, dev, NULL); - priv->stats.tx_errors++; - netif_wake_queue(dev); - return; -} - -/** - * @brief WILC_WFI_Ioctl - * @details Ioctl commands - * @param[in] net_device *dev: - * @param[in] ifreq *rq - * @param[in] cmd: - * @return int : Return 0 on Success - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -int WILC_WFI_Ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - PRINT_D(RX_DBG, "ioctl\n"); - return 0; -} - -/** - * @brief WILC_WFI_Stat - * @details Return statistics to the caller - * @param[in] net_device *dev: - * @return WILC_WFI_Stats : Return net_device_stats stucture with the - * network device driver private data contents. - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -struct net_device_stats *WILC_WFI_Stats(struct net_device *dev) -{ - struct WILC_WFI_priv *priv = netdev_priv(dev); - - return &priv->stats; -} - -/** - * @brief WILC_WFI_RebuildHeader - * @details This function is called to fill up an eth header, since arp is not - * available on the interface - * @param[in] sk_buff *skb: - * @return int : Return 0 on Success - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -int WILC_WFI_RebuildHeader(struct sk_buff *skb) -{ - struct ethhdr *eth = (struct ethhdr *) skb->data; - struct net_device *dev = skb->dev; - - memcpy(eth->h_source, dev->dev_addr, dev->addr_len); - memcpy(eth->h_dest, dev->dev_addr, dev->addr_len); - eth->h_dest[ETH_ALEN - 1] ^= 0x01; /* dest is us xor 1 */ - return 0; -} -/** - * @brief WILC_WFI_RebuildHeader - * @details This function is called to fill up an eth header, since arp is not - * available on the interface - * @param[in] sk_buff *skb: - * @param[in] struct net_device *dev: - * @param[in] unsigned short type: - * @param[in] const void *saddr, - * @param[in] const void *daddr: - * @param[in] unsigned int len - * @return int : Return 0 on Success - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -int WILC_WFI_Header(struct sk_buff *skb, struct net_device *dev, - unsigned short type, const void *daddr, const void *saddr, - unsigned int len) -{ - struct ethhdr *eth = (struct ethhdr *)skb_push(skb, ETH_HLEN); - - eth->h_proto = htons(type); - memcpy(eth->h_source, saddr ? saddr : dev->dev_addr, dev->addr_len); - memcpy(eth->h_dest, daddr ? daddr : dev->dev_addr, dev->addr_len); - eth->h_dest[ETH_ALEN - 1] ^= 0x01; /* dest is us xor 1 */ - return dev->hard_header_len; -} - -/** - * @brief WILC_WFI_ChangeMtu - * @details The "change_mtu" method is usually not needed. - * If you need it, it must be like this. - * @param[in] net_device *dev : Network Device Driver Structure - * @param[in] new_mtu : - * @return int : Returns 0 on Success. - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -int WILC_WFI_ChangeMtu(struct net_device *dev, int new_mtu) -{ - unsigned long flags; - struct WILC_WFI_priv *priv = netdev_priv(dev); - spinlock_t *lock = &priv->lock; - - /* check ranges */ - if ((new_mtu < 68) || (new_mtu > 1500)) - return -EINVAL; - /* - * Do anything you need, and the accept the value - */ - spin_lock_irqsave(lock, flags); - dev->mtu = new_mtu; - spin_unlock_irqrestore(lock, flags); - return 0; /* success */ -} - -static const struct header_ops WILC_WFI_header_ops = { - .create = WILC_WFI_Header, - .rebuild = WILC_WFI_RebuildHeader, - .cache = NULL, /* disable caching */ -}; - - -static const struct net_device_ops WILC_WFI_netdev_ops = { - .ndo_open = WILC_WFI_Open, - .ndo_stop = WILC_WFI_Release, - .ndo_set_config = WILC_WFI_Config, - .ndo_start_xmit = WILC_WFI_Tx, - .ndo_do_ioctl = WILC_WFI_Ioctl, - .ndo_get_stats = WILC_WFI_Stats, - .ndo_change_mtu = WILC_WFI_ChangeMtu, - .ndo_tx_timeout = WILC_WFI_TxTimeout, -}; - -/** - * @brief WILC_WFI_Init - * @details The init function (sometimes called probe). - * It is invoked by register_netdev() - * @param[in] net_device *dev: - * @return NONE - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -void WILC_WFI_Init(struct net_device *dev) -{ - struct WILC_WFI_priv *priv; - - /* - * Then, assign other fields in dev, using ether_setup() and some - * hand assignments - */ - ether_setup(dev); /* assign some of the fields */ - /* 1- Allocate space */ - - dev->netdev_ops = &WILC_WFI_netdev_ops; - dev->header_ops = &WILC_WFI_header_ops; - dev->watchdog_timeo = timeout; - /* keep the default flags, just add NOARP */ - dev->flags |= IFF_NOARP; - dev->features |= NETIF_F_NO_CSUM; - /* - * Then, initialize the priv field. This encloses the statistics - * and a few private fields. - */ - priv = netdev_priv(dev); - memset(priv, 0, sizeof(struct WILC_WFI_priv)); - priv->dev = dev; - netif_napi_add(dev, &priv->napi, WILC_WFI_Poll, 2); - /* The last parameter above is the NAPI "weight". */ - spin_lock_init(&priv->lock); - WILC_WFI_RxInts(dev, 1); /* enable receive interrupts */ - WILC_WFI_SetupPool(dev); -} - -/** - * @brief WILC_WFI_Stat - * @details Return statistics to the caller - * @param[in] net_device *dev: - * @return WILC_WFI_Stats : Return net_device_stats stucture with the - * network device driver private data contents. - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ - -void WILC_WFI_Cleanup(void) -{ - int i; - struct WILC_WFI_priv *priv[2]; - - for (i = 0; i < 2; i++) { - priv[i] = netdev_priv(WILC_WFI_devs[i]); - - if (WILC_WFI_devs[i]) { - PRINT_D(RX_DBG, "Unregistering\n"); - unregister_netdev(WILC_WFI_devs[i]); - WILC_WFI_TearDownPool(WILC_WFI_devs[i]); - free_netdev(WILC_WFI_devs[i]); - PRINT_D(RX_DBG, "[NETDEV]Stopping interface\n"); - WILC_WFI_DeInitHostInt(WILC_WFI_devs[i]); - WILC_WFI_WiphyFree(WILC_WFI_devs[i]); - } - - } - /* unregister_netdev(hwsim_mon); */ - WILC_WFI_deinit_mon_interface(); - return; -} - - -void StartConfigSim(void); - -/** - * @brief WILC_WFI_Stat - * @details Return statistics to the caller - * @param[in] net_device *dev: - * @return WILC_WFI_Stats : Return net_device_stats stucture with the - * network device driver private data contents. - * @author mdaftedar - * @date 01 MAR 2012 - * @version 1.0 - */ -int WILC_WFI_InitModule(void) -{ - - int result, i, ret = -ENOMEM; - struct WILC_WFI_priv *priv[2], *netpriv; - struct wireless_dev *wdev; - - WILC_WFI_Interrupt = use_napi ? WILC_WFI_NapiInterrupt : WILC_WFI_RegularInterrupt; - - for (i = 0; i < 2; i++) { - /* Allocate the net devices */ - WILC_WFI_devs[i] = alloc_netdev(sizeof(struct WILC_WFI_priv), "wlan%d", - WILC_WFI_Init); - if (WILC_WFI_devs[i] == NULL) - goto out; - - wdev = WILC_WFI_WiphyRegister(WILC_WFI_devs[i]); - WILC_WFI_devs[i]->ieee80211_ptr = wdev; - netpriv = netdev_priv(WILC_WFI_devs[i]); - netpriv->dev->ieee80211_ptr = wdev; - netpriv->dev->ml_priv = netpriv; - wdev->netdev = netpriv->dev; - - /*Registering the net device*/ - result = register_netdev(WILC_WFI_devs[i]); - if (result) - PRINT_D(RX_DBG, "WILC_WFI: error %i registering device \"%s\"\n", - result, WILC_WFI_devs[i]->name); - else - ret = 0; - } - - /*init atmel driver */ - priv[0] = netdev_priv(WILC_WFI_devs[0]); - priv[1] = netdev_priv(WILC_WFI_devs[1]); - - priv[0]->bCfgScanning = false; - priv[0]->u32RcvdChCount = 0; - - WILC_memset(priv[0]->au8AssociatedBss, 0xFF, ETH_ALEN); - - if (ret) - PRINT_ER("Error Init Driver\n"); - -out: - if (ret) - WILC_WFI_Cleanup(); - return ret; - - -} - -module_init(WILC_WFI_InitModule); -module_exit(WILC_WFI_Cleanup); - -#endif diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index def72fd1236d..192f36cde59e 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -16,7 +16,6 @@ * Global * ********************************************/ -extern unsigned int int_clrd; extern wilc_hif_func_t hif_sdio; extern wilc_hif_func_t hif_spi; extern wilc_cfg_func_t mac_cfg; @@ -24,8 +23,6 @@ extern wilc_cfg_func_t mac_cfg; extern u8 g_wilc_initialized; /* AMR : 0422 RK3026 Crash issue */ #endif extern void WILC_WFI_mgmt_rx(uint8_t *buff, uint32_t size); -extern void frmw_to_linux(uint8_t *buff, uint32_t size); -int sdio_xfer_cnt(void); uint32_t wilc_get_chipid(uint8_t update); u16 Set_machw_change_vir_if(bool bValue); @@ -291,13 +288,13 @@ uint32_t Statisitcs_totalAcks = 0, Statisitcs_DroppedAcks = 0; #ifdef TCP_ACK_FILTER struct Ack_session_info; -typedef struct Ack_session_info { +struct Ack_session_info { uint32_t Ack_seq_num; uint32_t Bigger_Ack_num; uint16_t src_port; uint16_t dst_port; uint16_t status; -} Ack_session_info_t; +}; typedef struct { uint32_t ack_num; @@ -318,7 +315,7 @@ struct Ack_session_info *Alloc_head; #define MAX_TCP_SESSION 25 #define MAX_PENDING_ACKS 256 -Ack_session_info_t Acks_keep_track_info[2 * MAX_TCP_SESSION]; +struct Ack_session_info Acks_keep_track_info[2 * MAX_TCP_SESSION]; Pending_Acks_info_t Pending_Acks_info[MAX_PENDING_ACKS]; uint32_t PendingAcks_arrBase; @@ -450,7 +447,7 @@ static int wilc_wlan_txq_filter_dup_tcp_ack(void) for (i = PendingAcks_arrBase; i < (PendingAcks_arrBase + Pending_Acks); i++) { if (Pending_Acks_info[i].ack_num < Acks_keep_track_info[Pending_Acks_info[i].Session_index].Bigger_Ack_num) { struct txq_entry_t *tqe; - PRINT_D(TCP_ENH, "DROP ACK: %u \n", Pending_Acks_info[i].ack_num); + PRINT_D(TCP_ENH, "DROP ACK: %u\n", Pending_Acks_info[i].ack_num); tqe = Pending_Acks_info[i].txqe; if (tqe) { wilc_wlan_txq_remove(tqe); @@ -466,11 +463,10 @@ static int wilc_wlan_txq_filter_dup_tcp_ack(void) Pending_Acks = 0; Opened_TCP_session = 0; - if (PendingAcks_arrBase == 0) { + if (PendingAcks_arrBase == 0) PendingAcks_arrBase = MAX_TCP_SESSION; - } else { + else PendingAcks_arrBase = 0; - } p->os_func.os_spin_unlock(p->txq_spinlock, &p->txq_spinlock_flags); @@ -995,7 +991,7 @@ static int wilc_wlan_handle_txq(uint32_t *pu32TxqCount) /** * wait for vmm table is ready **/ - PRINT_WRN(GENERIC_DBG, "[wilc txq]: warn, vmm table not clear yet, wait... \n"); + PRINT_WRN(GENERIC_DBG, "[wilc txq]: warn, vmm table not clear yet, wait...\n"); release_bus(RELEASE_ALLOW_SLEEP); p->os_func.os_sleep(3); /* wait 3 ms */ acquire_bus(ACQUIRE_AND_WAKEUP); @@ -1062,7 +1058,7 @@ static int wilc_wlan_handle_txq(uint32_t *pu32TxqCount) } if (entries == 0) { - PRINT_WRN(GENERIC_DBG, "[wilc txq]: no more buffer in the chip (reg: %08x), retry later [[ %d, %x ]] \n", reg, i, vmm_table[i - 1]); + PRINT_WRN(GENERIC_DBG, "[wilc txq]: no more buffer in the chip (reg: %08x), retry later [[ %d, %x ]]\n", reg, i, vmm_table[i - 1]); /* undo the transaction. */ ret = p->hif_func.hif_read_reg(WILC_HOST_TX_CTRL, ®); @@ -1113,11 +1109,10 @@ static int wilc_wlan_handle_txq(uint32_t *pu32TxqCount) /*Bug3959: transmitting mgmt frames received from host*/ /*setting bit 30 in the host header to indicate mgmt frame*/ #ifdef WILC_AP_EXTERNAL_MLME - if (tqe->type == WILC_MGMT_PKT) { + if (tqe->type == WILC_MGMT_PKT) header |= (1 << 30); - } else { + else header &= ~(1 << 30); - } #endif #ifdef BIG_ENDIAN @@ -1212,7 +1207,7 @@ static void wilc_wlan_handle_rxq(void) do { if (p->quit) { - PRINT_D(RX_DBG, "exit 1st do-while due to Clean_UP function \n"); + PRINT_D(RX_DBG, "exit 1st do-while due to Clean_UP function\n"); p->os_func.os_signal(p->cfg_wait); break; } @@ -1329,7 +1324,7 @@ static void wilc_wlan_handle_rxq(void) } while (1); p->rxq_exit = 1; - PRINT_D(RX_DBG, "THREAD: Exiting RX thread \n"); + PRINT_D(RX_DBG, "THREAD: Exiting RX thread\n"); return; } @@ -1544,11 +1539,10 @@ static int wilc_wlan_firmware_download(const uint8_t *buffer, uint32_t buffer_si acquire_bus(ACQUIRE_ONLY); offset += 8; while (((int)size) && (offset < buffer_size)) { - if (size <= blksz) { + if (size <= blksz) size2 = size; - } else { + else size2 = blksz; - } /* Copy firmware into a DMA coherent buffer */ memcpy(dma_buffer, &buffer[offset], size2); ret = p->hif_func.hif_block_tx(addr, dma_buffer, size2); @@ -2305,11 +2299,10 @@ u16 Set_machw_change_vir_if(bool bValue) PRINT_ER("Error while Reading reg WILC_CHANGING_VIR_IF\n"); } - if (bValue) { + if (bValue) reg |= (BIT31); - } else { + else reg &= ~(BIT31); - } ret = (&g_wlan)->hif_func.hif_write_reg(WILC_CHANGING_VIR_IF, reg); diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.c b/drivers/staging/wilc1000/wilc_wlan_cfg.c index 04d032783dae..c10dffe4633e 100644 --- a/drivers/staging/wilc1000/wilc_wlan_cfg.c +++ b/drivers/staging/wilc1000/wilc_wlan_cfg.c @@ -551,7 +551,7 @@ static int wilc_wlan_cfg_indicate_rx(uint8_t *frame, int size, wilc_cfg_rsp_t *r case 'L': #ifndef SWITCH_LOG_TERMINAL - PRINT_ER("Unexpected firmware log message received \n"); + PRINT_ER("Unexpected firmware log message received\n"); #else PRINT_D(FIRM_DBG, "\nFIRMWARE LOGS :\n<<\n%s\n>>\n", frame); break; @@ -566,18 +566,18 @@ static int wilc_wlan_cfg_indicate_rx(uint8_t *frame, int size, wilc_cfg_rsp_t *r #endif /*bug3819:*/ case 'S': - PRINT_INFO(RX_DBG, "Scan Notification Received \n"); + PRINT_INFO(RX_DBG, "Scan Notification Received\n"); host_int_ScanCompleteReceived(frame - 4, size + 4); break; #ifdef WILC_FULLY_HOSTING_AP case 'T': - PRINT_INFO(RX_DBG, "TBTT Notification Received \n"); + PRINT_INFO(RX_DBG, "TBTT Notification Received\n"); process_tbtt_isr(); break; case 'A': - PRINT_INFO(RX_DBG, "HOSTAPD ACK Notification Received \n"); + PRINT_INFO(RX_DBG, "HOSTAPD ACK Notification Received\n"); WILC_mgm_HOSTAPD_ACK(ptru32Frame, bStatus); break; #endif diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 5bfe151ea328..5a6251a45112 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -29,7 +29,7 @@ static unsigned int refresh_rate; /* -------------------- Macro definitions ---------------------------- */ #ifdef DEBUG -static void dumpVGAReg(void) +static void dumpVGAReg(struct xgifb_video_info *xgifb_info) { u8 i, reg; @@ -48,7 +48,7 @@ static void dumpVGAReg(void) } } #else -static inline void dumpVGAReg(void) +static inline void dumpVGAReg(struct xgifb_video_info *xgifb_info) { } #endif @@ -1073,7 +1073,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, } XGIfb_bpp_to_var(xgifb_info, var); /*update ARGB info*/ - dumpVGAReg(); + dumpVGAReg(xgifb_info); return 0; } @@ -2019,7 +2019,7 @@ static int xgifb_probe(struct pci_dev *pdev, goto error_mtrr; } - dumpVGAReg(); + dumpVGAReg(xgifb_info); return 0; diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 4e68b62193ed..cd77a064c772 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3998,7 +3998,13 @@ get_immediate: } transport_err: - iscsit_take_action_for_connection_exit(conn); + /* + * Avoid the normal connection failure code-path if this connection + * is still within LOGIN mode, and iscsi_np process context is + * responsible for cleaning up the early connection failure. + */ + if (conn->conn_state != TARG_CONN_STATE_IN_LOGIN) + iscsit_take_action_for_connection_exit(conn); out: return 0; } @@ -4082,7 +4088,7 @@ reject: int iscsi_target_rx_thread(void *arg) { - int ret; + int ret, rc; u8 buffer[ISCSI_HDR_LEN], opcode; u32 checksum = 0, digest = 0; struct iscsi_conn *conn = arg; @@ -4092,10 +4098,16 @@ int iscsi_target_rx_thread(void *arg) * connection recovery / failure event can be triggered externally. */ allow_signal(SIGINT); + /* + * Wait for iscsi_post_login_handler() to complete before allowing + * incoming iscsi/tcp socket I/O, and/or failing the connection. + */ + rc = wait_for_completion_interruptible(&conn->rx_login_comp); + if (rc < 0) + return 0; if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) { struct completion comp; - int rc; init_completion(&comp); rc = wait_for_completion_interruptible(&comp); @@ -4532,7 +4544,18 @@ static void iscsit_logout_post_handler_closesession( struct iscsi_conn *conn) { struct iscsi_session *sess = conn->sess; - int sleep = cmpxchg(&conn->tx_thread_active, true, false); + int sleep = 1; + /* + * Traditional iscsi/tcp will invoke this logic from TX thread + * context during session logout, so clear tx_thread_active and + * sleep if iscsit_close_connection() has not already occured. + * + * Since iser-target invokes this logic from it's own workqueue, + * always sleep waiting for RX/TX thread shutdown to complete + * within iscsit_close_connection(). + */ + if (conn->conn_transport->transport_type == ISCSI_TCP) + sleep = cmpxchg(&conn->tx_thread_active, true, false); atomic_set(&conn->conn_logout_remove, 0); complete(&conn->conn_logout_comp); @@ -4546,7 +4569,10 @@ static void iscsit_logout_post_handler_closesession( static void iscsit_logout_post_handler_samecid( struct iscsi_conn *conn) { - int sleep = cmpxchg(&conn->tx_thread_active, true, false); + int sleep = 1; + + if (conn->conn_transport->transport_type == ISCSI_TCP) + sleep = cmpxchg(&conn->tx_thread_active, true, false); atomic_set(&conn->conn_logout_remove, 0); complete(&conn->conn_logout_comp); @@ -4765,6 +4791,7 @@ int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force) struct iscsi_session *sess; struct se_portal_group *se_tpg = &tpg->tpg_se_tpg; struct se_session *se_sess, *se_sess_tmp; + LIST_HEAD(free_list); int session_count = 0; spin_lock_bh(&se_tpg->session_lock); @@ -4786,14 +4813,17 @@ int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force) } atomic_set(&sess->session_reinstatement, 1); spin_unlock(&sess->conn_lock); - spin_unlock_bh(&se_tpg->session_lock); - iscsit_free_session(sess); - spin_lock_bh(&se_tpg->session_lock); + list_move_tail(&se_sess->sess_list, &free_list); + } + spin_unlock_bh(&se_tpg->session_lock); + + list_for_each_entry_safe(se_sess, se_sess_tmp, &free_list, sess_list) { + sess = (struct iscsi_session *)se_sess->fabric_sess_ptr; + iscsit_free_session(sess); session_count++; } - spin_unlock_bh(&se_tpg->session_lock); pr_debug("Released %d iSCSI Session(s) from Target Portal" " Group: %hu\n", session_count, tpg->tpgt); diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 3d0fe4ff5590..7e8f65e5448f 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -82,6 +82,7 @@ static struct iscsi_login *iscsi_login_init_conn(struct iscsi_conn *conn) init_completion(&conn->conn_logout_comp); init_completion(&conn->rx_half_close_comp); init_completion(&conn->tx_half_close_comp); + init_completion(&conn->rx_login_comp); spin_lock_init(&conn->cmd_lock); spin_lock_init(&conn->conn_usage_lock); spin_lock_init(&conn->immed_queue_lock); @@ -644,7 +645,7 @@ static void iscsi_post_login_start_timers(struct iscsi_conn *conn) iscsit_start_nopin_timer(conn); } -static int iscsit_start_kthreads(struct iscsi_conn *conn) +int iscsit_start_kthreads(struct iscsi_conn *conn) { int ret = 0; @@ -679,6 +680,7 @@ static int iscsit_start_kthreads(struct iscsi_conn *conn) return 0; out_tx: + send_sig(SIGINT, conn->tx_thread, 1); kthread_stop(conn->tx_thread); conn->tx_thread_active = false; out_bitmap: @@ -689,7 +691,7 @@ out_bitmap: return ret; } -int iscsi_post_login_handler( +void iscsi_post_login_handler( struct iscsi_np *np, struct iscsi_conn *conn, u8 zero_tsih) @@ -699,7 +701,6 @@ int iscsi_post_login_handler( struct se_session *se_sess = sess->se_sess; struct iscsi_portal_group *tpg = sess->tpg; struct se_portal_group *se_tpg = &tpg->tpg_se_tpg; - int rc; iscsit_inc_conn_usage_count(conn); @@ -739,10 +740,6 @@ int iscsi_post_login_handler( sess->sess_ops->InitiatorName); spin_unlock_bh(&sess->conn_lock); - rc = iscsit_start_kthreads(conn); - if (rc) - return rc; - iscsi_post_login_start_timers(conn); /* * Determine CPU mask to ensure connection's RX and TX kthreads @@ -751,15 +748,20 @@ int iscsi_post_login_handler( iscsit_thread_get_cpumask(conn); conn->conn_rx_reset_cpumask = 1; conn->conn_tx_reset_cpumask = 1; - + /* + * Wakeup the sleeping iscsi_target_rx_thread() now that + * iscsi_conn is in TARG_CONN_STATE_LOGGED_IN state. + */ + complete(&conn->rx_login_comp); iscsit_dec_conn_usage_count(conn); + if (stop_timer) { spin_lock_bh(&se_tpg->session_lock); iscsit_stop_time2retain_timer(sess); spin_unlock_bh(&se_tpg->session_lock); } iscsit_dec_session_usage_count(sess); - return 0; + return; } iscsi_set_session_parameters(sess->sess_ops, conn->param_list, 1); @@ -800,10 +802,6 @@ int iscsi_post_login_handler( " iSCSI Target Portal Group: %hu\n", tpg->nsessions, tpg->tpgt); spin_unlock_bh(&se_tpg->session_lock); - rc = iscsit_start_kthreads(conn); - if (rc) - return rc; - iscsi_post_login_start_timers(conn); /* * Determine CPU mask to ensure connection's RX and TX kthreads @@ -812,10 +810,12 @@ int iscsi_post_login_handler( iscsit_thread_get_cpumask(conn); conn->conn_rx_reset_cpumask = 1; conn->conn_tx_reset_cpumask = 1; - + /* + * Wakeup the sleeping iscsi_target_rx_thread() now that + * iscsi_conn is in TARG_CONN_STATE_LOGGED_IN state. + */ + complete(&conn->rx_login_comp); iscsit_dec_conn_usage_count(conn); - - return 0; } static void iscsi_handle_login_thread_timeout(unsigned long data) @@ -1380,23 +1380,12 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) if (ret < 0) goto new_sess_out; - if (!conn->sess) { - pr_err("struct iscsi_conn session pointer is NULL!\n"); - goto new_sess_out; - } - iscsi_stop_login_thread_timer(np); - if (signal_pending(current)) - goto new_sess_out; - if (ret == 1) { tpg_np = conn->tpg_np; - ret = iscsi_post_login_handler(np, conn, zero_tsih); - if (ret < 0) - goto new_sess_out; - + iscsi_post_login_handler(np, conn, zero_tsih); iscsit_deaccess_np(np, tpg, tpg_np); } diff --git a/drivers/target/iscsi/iscsi_target_login.h b/drivers/target/iscsi/iscsi_target_login.h index 1c7358081533..57aa0d0fd820 100644 --- a/drivers/target/iscsi/iscsi_target_login.h +++ b/drivers/target/iscsi/iscsi_target_login.h @@ -12,7 +12,8 @@ extern int iscsit_accept_np(struct iscsi_np *, struct iscsi_conn *); extern int iscsit_get_login_rx(struct iscsi_conn *, struct iscsi_login *); extern int iscsit_put_login_tx(struct iscsi_conn *, struct iscsi_login *, u32); extern void iscsit_free_conn(struct iscsi_np *, struct iscsi_conn *); -extern int iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8); +extern int iscsit_start_kthreads(struct iscsi_conn *); +extern void iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8); extern void iscsi_target_login_sess_out(struct iscsi_conn *, struct iscsi_np *, bool, bool); extern int iscsi_target_login_thread(void *); diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index 8c02fa34716f..f9cde9141836 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c @@ -17,6 +17,7 @@ ******************************************************************************/ #include <linux/ctype.h> +#include <linux/kthread.h> #include <scsi/iscsi_proto.h> #include <target/target_core_base.h> #include <target/target_core_fabric.h> @@ -361,10 +362,24 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log ntohl(login_rsp->statsn), login->rsp_length); padding = ((-login->rsp_length) & 3); + /* + * Before sending the last login response containing the transition + * bit for full-feature-phase, go ahead and start up TX/RX threads + * now to avoid potential resource allocation failures after the + * final login response has been sent. + */ + if (login->login_complete) { + int rc = iscsit_start_kthreads(conn); + if (rc) { + iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, + ISCSI_LOGIN_STATUS_NO_RESOURCES); + return -1; + } + } if (conn->conn_transport->iscsit_put_login_tx(conn, login, login->rsp_length + padding) < 0) - return -1; + goto err; login->rsp_length = 0; mutex_lock(&sess->cmdsn_mutex); @@ -373,6 +388,23 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log mutex_unlock(&sess->cmdsn_mutex); return 0; + +err: + if (login->login_complete) { + if (conn->rx_thread && conn->rx_thread_active) { + send_sig(SIGINT, conn->rx_thread, 1); + kthread_stop(conn->rx_thread); + } + if (conn->tx_thread && conn->tx_thread_active) { + send_sig(SIGINT, conn->tx_thread, 1); + kthread_stop(conn->tx_thread); + } + spin_lock(&iscsit_global->ts_bitmap_lock); + bitmap_release_region(iscsit_global->ts_bitmap, conn->bitmap_id, + get_order(1)); + spin_unlock(&iscsit_global->ts_bitmap_lock); + } + return -1; } static void iscsi_target_sk_data_ready(struct sock *sk) diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 0b0de3647478..c2e9fea90b4a 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -747,7 +747,7 @@ static ssize_t store_pi_prot_type(struct se_dev_attrib *da, if (!dev->transport->init_prot || !dev->transport->free_prot) { /* 0 is only allowed value for non-supporting backends */ if (flag == 0) - return 0; + return count; pr_err("DIF protection not supported by backend: %s\n", dev->transport->name); @@ -1590,9 +1590,9 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( u8 type = 0; if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH) - return 0; + return count; if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) - return 0; + return count; if (dev->export_count) { pr_debug("Unable to process APTPL metadata while" @@ -1658,22 +1658,32 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( * PR APTPL Metadata for Reservation */ case Opt_res_holder: - match_int(args, &arg); + ret = match_int(args, &arg); + if (ret) + goto out; res_holder = arg; break; case Opt_res_type: - match_int(args, &arg); + ret = match_int(args, &arg); + if (ret) + goto out; type = (u8)arg; break; case Opt_res_scope: - match_int(args, &arg); + ret = match_int(args, &arg); + if (ret) + goto out; break; case Opt_res_all_tg_pt: - match_int(args, &arg); + ret = match_int(args, &arg); + if (ret) + goto out; all_tg_pt = (int)arg; break; case Opt_mapped_lun: - match_int(args, &arg); + ret = match_int(args, &arg); + if (ret) + goto out; mapped_lun = (u64)arg; break; /* @@ -1701,14 +1711,20 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( } break; case Opt_tpgt: - match_int(args, &arg); + ret = match_int(args, &arg); + if (ret) + goto out; tpgt = (u16)arg; break; case Opt_port_rtpi: - match_int(args, &arg); + ret = match_int(args, &arg); + if (ret) + goto out; break; case Opt_target_lun: - match_int(args, &arg); + ret = match_int(args, &arg); + if (ret) + goto out; target_lun = (u64)arg; break; default: @@ -1985,7 +2001,7 @@ static ssize_t target_core_store_alua_lu_gp( lu_gp_mem = dev->dev_alua_lu_gp_mem; if (!lu_gp_mem) - return 0; + return count; if (count > LU_GROUP_NAME_BUF) { pr_err("ALUA LU Group Alias too large!\n"); diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 0fdbe43b7dad..5ab7100de17e 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -1474,7 +1474,7 @@ core_scsi3_decode_spec_i_port( LIST_HEAD(tid_dest_list); struct pr_transport_id_holder *tidh_new, *tidh, *tidh_tmp; unsigned char *buf, *ptr, proto_ident; - const unsigned char *i_str; + const unsigned char *i_str = NULL; char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN]; sense_reason_t ret; u32 tpdl, tid_len = 0; diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index 4703f403f31c..384cf8894411 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c @@ -333,6 +333,7 @@ static int rd_configure_device(struct se_device *dev) dev->dev_attrib.hw_block_size = RD_BLOCKSIZE; dev->dev_attrib.hw_max_sectors = UINT_MAX; dev->dev_attrib.hw_queue_depth = RD_MAX_DEVICE_QUEUE_DEPTH; + dev->dev_attrib.is_nonrot = 1; rd_dev->rd_dev_id = rd_host->rd_host_dev_id_count++; diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index b0744433315a..b5ba1ec3c354 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -454,10 +454,17 @@ spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) cmd->se_sess->sess_prot_type == TARGET_DIF_TYPE1_PROT) buf[4] = 0x5; else if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE3_PROT || - cmd->se_sess->sess_prot_type == TARGET_DIF_TYPE3_PROT) + cmd->se_sess->sess_prot_type == TARGET_DIF_TYPE3_PROT) buf[4] = 0x4; } + /* logical unit supports type 1 and type 3 protection */ + if ((dev->transport->get_device_type(dev) == TYPE_DISK) && + (sess->sup_prot_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS)) && + (dev->dev_attrib.pi_prot_type || cmd->se_sess->sess_prot_type)) { + buf[4] |= (0x3 << 3); + } + /* Set HEADSUP, ORDSUP, SIMPSUP */ buf[5] = 0x07; diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index d5dd357ba57c..b49f97c734d0 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -405,7 +405,6 @@ static SIMPLE_DEV_PM_OPS(hisi_thermal_pm_ops, static struct platform_driver hisi_thermal_driver = { .driver = { .name = "hisi_thermal", - .owner = THIS_MODULE, .pm = &hisi_thermal_pm_ops, .of_match_table = of_hisi_thermal_match, }, diff --git a/drivers/thermal/power_allocator.c b/drivers/thermal/power_allocator.c index 4672250b329f..63a448f9d93b 100644 --- a/drivers/thermal/power_allocator.c +++ b/drivers/thermal/power_allocator.c @@ -229,7 +229,8 @@ static int allocate_power(struct thermal_zone_device *tz, struct thermal_instance *instance; struct power_allocator_params *params = tz->governor_data; u32 *req_power, *max_power, *granted_power, *extra_actor_power; - u32 total_req_power, max_allocatable_power; + u32 *weighted_req_power; + u32 total_req_power, max_allocatable_power, total_weighted_req_power; u32 total_granted_power, power_range; int i, num_actors, total_weight, ret = 0; int trip_max_desired_temperature = params->trip_max_desired_temperature; @@ -247,16 +248,17 @@ static int allocate_power(struct thermal_zone_device *tz, } /* - * We need to allocate three arrays of the same size: - * req_power, max_power and granted_power. They are going to - * be needed until this function returns. Allocate them all - * in one go to simplify the allocation and deallocation - * logic. + * We need to allocate five arrays of the same size: + * req_power, max_power, granted_power, extra_actor_power and + * weighted_req_power. They are going to be needed until this + * function returns. Allocate them all in one go to simplify + * the allocation and deallocation logic. */ BUILD_BUG_ON(sizeof(*req_power) != sizeof(*max_power)); BUILD_BUG_ON(sizeof(*req_power) != sizeof(*granted_power)); BUILD_BUG_ON(sizeof(*req_power) != sizeof(*extra_actor_power)); - req_power = devm_kcalloc(&tz->device, num_actors * 4, + BUILD_BUG_ON(sizeof(*req_power) != sizeof(*weighted_req_power)); + req_power = devm_kcalloc(&tz->device, num_actors * 5, sizeof(*req_power), GFP_KERNEL); if (!req_power) { ret = -ENOMEM; @@ -266,8 +268,10 @@ static int allocate_power(struct thermal_zone_device *tz, max_power = &req_power[num_actors]; granted_power = &req_power[2 * num_actors]; extra_actor_power = &req_power[3 * num_actors]; + weighted_req_power = &req_power[4 * num_actors]; i = 0; + total_weighted_req_power = 0; total_req_power = 0; max_allocatable_power = 0; @@ -289,13 +293,14 @@ static int allocate_power(struct thermal_zone_device *tz, else weight = instance->weight; - req_power[i] = frac_to_int(weight * req_power[i]); + weighted_req_power[i] = frac_to_int(weight * req_power[i]); if (power_actor_get_max_power(cdev, tz, &max_power[i])) continue; total_req_power += req_power[i]; max_allocatable_power += max_power[i]; + total_weighted_req_power += weighted_req_power[i]; i++; } @@ -303,8 +308,9 @@ static int allocate_power(struct thermal_zone_device *tz, power_range = pid_controller(tz, current_temp, control_temp, max_allocatable_power); - divvy_up_power(req_power, max_power, num_actors, total_req_power, - power_range, granted_power, extra_actor_power); + divvy_up_power(weighted_req_power, max_power, num_actors, + total_weighted_req_power, power_range, granted_power, + extra_actor_power); total_granted_power = 0; i = 0; diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig index c8e35c1a43dc..e0da3865e060 100644 --- a/drivers/thermal/samsung/Kconfig +++ b/drivers/thermal/samsung/Kconfig @@ -1,6 +1,6 @@ config EXYNOS_THERMAL tristate "Exynos thermal management unit driver" - depends on OF + depends on THERMAL_OF help If you say yes here you get support for the TMU (Thermal Management Unit) driver for SAMSUNG EXYNOS series of SoCs. This driver initialises diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 531f4b179871..c96ff10b869e 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -1296,7 +1296,6 @@ static struct thermal_zone_of_device_ops exynos_sensor_ops = { static int exynos_tmu_probe(struct platform_device *pdev) { - struct exynos_tmu_platform_data *pdata; struct exynos_tmu_data *data; int ret; @@ -1318,8 +1317,6 @@ static int exynos_tmu_probe(struct platform_device *pdev) if (ret) goto err_sensor; - pdata = data->pdata; - INIT_WORK(&data->irq_work, exynos_tmu_work); data->clk = devm_clk_get(&pdev->dev, "tmu_apbif"); @@ -1392,6 +1389,8 @@ err_clk_sec: if (!IS_ERR(data->clk_sec)) clk_unprepare(data->clk_sec); err_sensor: + if (!IS_ERR_OR_NULL(data->regulator)) + regulator_disable(data->regulator); thermal_zone_of_sensor_unregister(&pdev->dev, data->tzd); return ret; diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 04659bfb888b..4ca211be4c0f 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1333,6 +1333,7 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, return -ENODEV; unbind: + device_remove_file(&tz->device, &pos->weight_attr); device_remove_file(&tz->device, &pos->attr); sysfs_remove_link(&tz->device.kobj, pos->name); release_idr(&tz->idr, &tz->lock, pos->id); diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index c9c27f69e101..ee8bfacf2071 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1108,19 +1108,29 @@ static void eraser(unsigned char c, struct tty_struct *tty) * Locking: ctrl_lock */ -static void isig(int sig, struct tty_struct *tty) +static void __isig(int sig, struct tty_struct *tty) { - struct n_tty_data *ldata = tty->disc_data; struct pid *tty_pgrp = tty_get_pgrp(tty); if (tty_pgrp) { kill_pgrp(tty_pgrp, sig, 1); put_pid(tty_pgrp); } +} - if (!L_NOFLSH(tty)) { +static void isig(int sig, struct tty_struct *tty) +{ + struct n_tty_data *ldata = tty->disc_data; + + if (L_NOFLSH(tty)) { + /* signal only */ + __isig(sig, tty); + + } else { /* signal and flush */ up_read(&tty->termios_rwsem); down_write(&tty->termios_rwsem); + __isig(sig, tty); + /* clear echo buffer */ mutex_lock(&ldata->output_lock); ldata->echo_head = ldata->echo_tail = 0; diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 76e65b714471..15b4079a335e 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1185,7 +1185,7 @@ config SERIAL_SC16IS7XX_CORE config SERIAL_SC16IS7XX tristate "SC16IS7xx serial support" select SERIAL_CORE - depends on I2C || SPI_MASTER + depends on (SPI_MASTER && !I2C) || I2C help This selects support for SC16IS7xx serial ports. Supported ICs are SC16IS740, SC16IS741, SC16IS750, SC16IS752, diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 50cf5b10ceed..fd27e986b1dd 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2310,8 +2310,8 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, void __iomem *base; base = devm_ioremap_resource(dev, mmiobase); - if (!base) - return -ENOMEM; + if (IS_ERR(base)) + return PTR_ERR(base); index = pl011_probe_dt_alias(index, dev); diff --git a/drivers/tty/serial/etraxfs-uart.c b/drivers/tty/serial/etraxfs-uart.c index a57301a6fe42..679709f51fd4 100644 --- a/drivers/tty/serial/etraxfs-uart.c +++ b/drivers/tty/serial/etraxfs-uart.c @@ -950,7 +950,7 @@ static int etraxfs_uart_remove(struct platform_device *pdev) port = platform_get_drvdata(pdev); uart_remove_one_port(&etraxfs_uart_driver, port); - etraxfs_uart_ports[pdev->id] = NULL; + etraxfs_uart_ports[port->line] = NULL; return 0; } diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 2c90dc31bfaa..54fdc7866ea1 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1121,11 +1121,6 @@ static int imx_startup(struct uart_port *port) writel(temp & ~UCR4_DREN, sport->port.membase + UCR4); - /* Can we enable the DMA support? */ - if (is_imx6q_uart(sport) && !uart_console(port) && - !sport->dma_is_inited) - imx_uart_dma_init(sport); - spin_lock_irqsave(&sport->port.lock, flags); /* Reset fifo's and state machines */ i = 100; @@ -1143,9 +1138,6 @@ static int imx_startup(struct uart_port *port) writel(USR1_RTSD, sport->port.membase + USR1); writel(USR2_ORE, sport->port.membase + USR2); - if (sport->dma_is_inited && !sport->dma_is_enabled) - imx_enable_dma(sport); - temp = readl(sport->port.membase + UCR1); temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN; @@ -1316,6 +1308,11 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, } else { ucr2 |= UCR2_CTSC; } + + /* Can we enable the DMA support? */ + if (is_imx6q_uart(sport) && !uart_console(port) + && !sport->dma_is_inited) + imx_uart_dma_init(sport); } else { termios->c_cflag &= ~CRTSCTS; } @@ -1432,6 +1429,8 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, if (UART_ENABLE_MS(&sport->port, termios->c_cflag)) imx_enable_ms(&sport->port); + if (sport->dma_is_inited && !sport->dma_is_enabled) + imx_enable_dma(sport); spin_unlock_irqrestore(&sport->port.lock, flags); } diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 9e6576004a42..5ccc698cbbfa 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -354,6 +354,26 @@ static void sc16is7xx_port_write(struct uart_port *port, u8 reg, u8 val) (reg << SC16IS7XX_REG_SHIFT) | port->line, val); } +static void sc16is7xx_fifo_read(struct uart_port *port, unsigned int rxlen) +{ + struct sc16is7xx_port *s = dev_get_drvdata(port->dev); + u8 addr = (SC16IS7XX_RHR_REG << SC16IS7XX_REG_SHIFT) | port->line; + + regcache_cache_bypass(s->regmap, true); + regmap_raw_read(s->regmap, addr, s->buf, rxlen); + regcache_cache_bypass(s->regmap, false); +} + +static void sc16is7xx_fifo_write(struct uart_port *port, u8 to_send) +{ + struct sc16is7xx_port *s = dev_get_drvdata(port->dev); + u8 addr = (SC16IS7XX_THR_REG << SC16IS7XX_REG_SHIFT) | port->line; + + regcache_cache_bypass(s->regmap, true); + regmap_raw_write(s->regmap, addr, s->buf, to_send); + regcache_cache_bypass(s->regmap, false); +} + static void sc16is7xx_port_update(struct uart_port *port, u8 reg, u8 mask, u8 val) { @@ -508,10 +528,7 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen, s->buf[0] = sc16is7xx_port_read(port, SC16IS7XX_RHR_REG); bytes_read = 1; } else { - regcache_cache_bypass(s->regmap, true); - regmap_raw_read(s->regmap, SC16IS7XX_RHR_REG, - s->buf, rxlen); - regcache_cache_bypass(s->regmap, false); + sc16is7xx_fifo_read(port, rxlen); bytes_read = rxlen; } @@ -591,9 +608,8 @@ static void sc16is7xx_handle_tx(struct uart_port *port) s->buf[i] = xmit->buf[xmit->tail]; xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); } - regcache_cache_bypass(s->regmap, true); - regmap_raw_write(s->regmap, SC16IS7XX_THR_REG, s->buf, to_send); - regcache_cache_bypass(s->regmap, false); + + sc16is7xx_fifo_write(port, to_send); } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 7ae1592f7ec9..f36852067f20 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1418,7 +1418,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) mutex_lock(&port->mutex); uart_shutdown(tty, state); tty_port_tty_set(port, NULL); - tty->closing = 0; + spin_lock_irqsave(&port->lock, flags); if (port->blocked_open) { @@ -1444,6 +1444,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) mutex_unlock(&port->mutex); tty_ldisc_flush(tty); + tty->closing = 0; } static void uart_wait_until_sent(struct tty_struct *tty, int timeout) diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index ea27804d87af..381a2b13682c 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -356,6 +356,7 @@ int paste_selection(struct tty_struct *tty) schedule(); continue; } + __set_current_state(TASK_RUNNING); count = sel_buffer_lth - pasted; count = tty_ldisc_receive_buf(ld, sel_buffer + pasted, NULL, count); diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 8fe52989b380..4462d167900c 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -742,6 +742,8 @@ static void visual_init(struct vc_data *vc, int num, int init) __module_get(vc->vc_sw->owner); vc->vc_num = num; vc->vc_display_fg = &master_display_fg; + if (vc->vc_uni_pagedir_loc) + con_free_unimap(vc); vc->vc_uni_pagedir_loc = &vc->vc_uni_pagedir; vc->vc_uni_pagedir = NULL; vc->vc_hi_font_mask = 0; diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 74fea4fa41b1..3ad48e1c0c57 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -1024,7 +1024,18 @@ static struct platform_driver ci_hdrc_driver = { }, }; -module_platform_driver(ci_hdrc_driver); +static int __init ci_hdrc_platform_register(void) +{ + ci_hdrc_host_driver_init(); + return platform_driver_register(&ci_hdrc_driver); +} +module_init(ci_hdrc_platform_register); + +static void __exit ci_hdrc_platform_unregister(void) +{ + platform_driver_unregister(&ci_hdrc_driver); +} +module_exit(ci_hdrc_platform_unregister); MODULE_ALIAS("platform:ci_hdrc"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index 6cf87b8b13a8..7161439def19 100644 --- a/drivers/usb/chipidea/host.c +++ b/drivers/usb/chipidea/host.c @@ -249,9 +249,12 @@ int ci_hdrc_host_init(struct ci_hdrc *ci) rdrv->name = "host"; ci->roles[CI_ROLE_HOST] = rdrv; + return 0; +} + +void ci_hdrc_host_driver_init(void) +{ ehci_init_driver(&ci_ehci_hc_driver, &ehci_ci_overrides); orig_bus_suspend = ci_ehci_hc_driver.bus_suspend; ci_ehci_hc_driver.bus_suspend = ci_ehci_bus_suspend; - - return 0; } diff --git a/drivers/usb/chipidea/host.h b/drivers/usb/chipidea/host.h index 5707bf379bfb..0f12f131bdd3 100644 --- a/drivers/usb/chipidea/host.h +++ b/drivers/usb/chipidea/host.h @@ -5,6 +5,7 @@ int ci_hdrc_host_init(struct ci_hdrc *ci); void ci_hdrc_host_destroy(struct ci_hdrc *ci); +void ci_hdrc_host_driver_init(void); #else @@ -18,6 +19,11 @@ static inline void ci_hdrc_host_destroy(struct ci_hdrc *ci) } +static void ci_hdrc_host_driver_init(void) +{ + +} + #endif #endif /* __DRIVERS_USB_CHIPIDEA_HOST_H */ diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 519a77ba214c..b30e7423549b 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1944,6 +1944,7 @@ static void __exit acm_exit(void) usb_deregister(&acm_driver); tty_unregister_driver(acm_tty_driver); put_tty_driver(acm_tty_driver); + idr_destroy(&acm_minors); } module_init(acm_init); diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index 0e6f968e93fe..01c0c0477a9e 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -242,7 +242,7 @@ static int __init ulpi_init(void) { return bus_register(&ulpi_bus); } -module_init(ulpi_init); +subsys_initcall(ulpi_init); static void __exit ulpi_exit(void) { diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index be5b2074f906..cbcd0920fb51 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1022,9 +1022,12 @@ static int register_root_hub(struct usb_hcd *hcd) dev_name(&usb_dev->dev), retval); return (retval < 0) ? retval : -EMSGSIZE; } - if (usb_dev->speed == USB_SPEED_SUPER) { + + if (le16_to_cpu(usb_dev->descriptor.bcdUSB) >= 0x0201) { retval = usb_get_bos_descriptor(usb_dev); - if (retval < 0) { + if (!retval) { + usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev); + } else if (usb_dev->speed == USB_SPEED_SUPER) { mutex_unlock(&usb_bus_list_lock); dev_dbg(parent_dev, "can't read %s bos descriptor %d\n", dev_name(&usb_dev->dev), retval); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 43cb2f2e3b43..73dfa194160b 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -122,7 +122,7 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev) return usb_get_intfdata(hdev->actconfig->interface[0]); } -static int usb_device_supports_lpm(struct usb_device *udev) +int usb_device_supports_lpm(struct usb_device *udev) { /* USB 2.1 (and greater) devices indicate LPM support through * their USB 2.0 Extended Capabilities BOS descriptor. diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 7eb1e26798e5..457255a3306a 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -65,6 +65,7 @@ extern int usb_hub_init(void); extern void usb_hub_cleanup(void); extern int usb_major_init(void); extern void usb_major_cleanup(void); +extern int usb_device_supports_lpm(struct usb_device *udev); #ifdef CONFIG_PM diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index e5b546f1152e..c3cc1a78d1e2 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -72,17 +72,7 @@ static int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, "%s\n", __func__); /* Backup Host regs */ - hr = hsotg->hr_backup; - if (!hr) { - hr = devm_kzalloc(hsotg->dev, sizeof(*hr), GFP_KERNEL); - if (!hr) { - dev_err(hsotg->dev, "%s: can't allocate host regs\n", - __func__); - return -ENOMEM; - } - - hsotg->hr_backup = hr; - } + hr = &hsotg->hr_backup; hr->hcfg = readl(hsotg->regs + HCFG); hr->haintmsk = readl(hsotg->regs + HAINTMSK); for (i = 0; i < hsotg->core_params->host_channels; ++i) @@ -90,6 +80,7 @@ static int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg) hr->hprt0 = readl(hsotg->regs + HPRT0); hr->hfir = readl(hsotg->regs + HFIR); + hr->valid = true; return 0; } @@ -109,12 +100,13 @@ static int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, "%s\n", __func__); /* Restore host regs */ - hr = hsotg->hr_backup; - if (!hr) { + hr = &hsotg->hr_backup; + if (!hr->valid) { dev_err(hsotg->dev, "%s: no host registers to restore\n", __func__); return -EINVAL; } + hr->valid = false; writel(hr->hcfg, hsotg->regs + HCFG); writel(hr->haintmsk, hsotg->regs + HAINTMSK); @@ -152,17 +144,7 @@ static int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, "%s\n", __func__); /* Backup dev regs */ - dr = hsotg->dr_backup; - if (!dr) { - dr = devm_kzalloc(hsotg->dev, sizeof(*dr), GFP_KERNEL); - if (!dr) { - dev_err(hsotg->dev, "%s: can't allocate device regs\n", - __func__); - return -ENOMEM; - } - - hsotg->dr_backup = dr; - } + dr = &hsotg->dr_backup; dr->dcfg = readl(hsotg->regs + DCFG); dr->dctl = readl(hsotg->regs + DCTL); @@ -195,7 +177,7 @@ static int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg) dr->doeptsiz[i] = readl(hsotg->regs + DOEPTSIZ(i)); dr->doepdma[i] = readl(hsotg->regs + DOEPDMA(i)); } - + dr->valid = true; return 0; } @@ -215,12 +197,13 @@ static int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, "%s\n", __func__); /* Restore dev regs */ - dr = hsotg->dr_backup; - if (!dr) { + dr = &hsotg->dr_backup; + if (!dr->valid) { dev_err(hsotg->dev, "%s: no device registers to restore\n", __func__); return -EINVAL; } + dr->valid = false; writel(dr->dcfg, hsotg->regs + DCFG); writel(dr->dctl, hsotg->regs + DCTL); @@ -268,17 +251,7 @@ static int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg) int i; /* Backup global regs */ - gr = hsotg->gr_backup; - if (!gr) { - gr = devm_kzalloc(hsotg->dev, sizeof(*gr), GFP_KERNEL); - if (!gr) { - dev_err(hsotg->dev, "%s: can't allocate global regs\n", - __func__); - return -ENOMEM; - } - - hsotg->gr_backup = gr; - } + gr = &hsotg->gr_backup; gr->gotgctl = readl(hsotg->regs + GOTGCTL); gr->gintmsk = readl(hsotg->regs + GINTMSK); @@ -291,6 +264,7 @@ static int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg) for (i = 0; i < MAX_EPS_CHANNELS; i++) gr->dtxfsiz[i] = readl(hsotg->regs + DPTXFSIZN(i)); + gr->valid = true; return 0; } @@ -309,12 +283,13 @@ static int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, "%s\n", __func__); /* Restore global regs */ - gr = hsotg->gr_backup; - if (!gr) { + gr = &hsotg->gr_backup; + if (!gr->valid) { dev_err(hsotg->dev, "%s: no global registers to restore\n", __func__); return -EINVAL; } + gr->valid = false; writel(0xffffffff, hsotg->regs + GINTSTS); writel(gr->gotgctl, hsotg->regs + GOTGCTL); diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 53b8de03f102..0ed87620941b 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -492,6 +492,7 @@ struct dwc2_gregs_backup { u32 gdfifocfg; u32 dtxfsiz[MAX_EPS_CHANNELS]; u32 gpwrdn; + bool valid; }; /** @@ -521,6 +522,7 @@ struct dwc2_dregs_backup { u32 doepctl[MAX_EPS_CHANNELS]; u32 doeptsiz[MAX_EPS_CHANNELS]; u32 doepdma[MAX_EPS_CHANNELS]; + bool valid; }; /** @@ -538,6 +540,7 @@ struct dwc2_hregs_backup { u32 hcintmsk[MAX_EPS_CHANNELS]; u32 hprt0; u32 hfir; + bool valid; }; /** @@ -705,9 +708,9 @@ struct dwc2_hsotg { struct work_struct wf_otg; struct timer_list wkp_timer; enum dwc2_lx_state lx_state; - struct dwc2_gregs_backup *gr_backup; - struct dwc2_dregs_backup *dr_backup; - struct dwc2_hregs_backup *hr_backup; + struct dwc2_gregs_backup gr_backup; + struct dwc2_dregs_backup dr_backup; + struct dwc2_hregs_backup hr_backup; struct dentry *debug_root; struct debugfs_regset32 *regset; diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index b10377c65064..f845c41fe9e5 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -359,10 +359,9 @@ void dwc2_hcd_stop(struct dwc2_hsotg *hsotg) /* Caller must hold driver lock */ static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg, - struct dwc2_hcd_urb *urb, void **ep_handle, - gfp_t mem_flags) + struct dwc2_hcd_urb *urb, struct dwc2_qh *qh, + struct dwc2_qtd *qtd) { - struct dwc2_qtd *qtd; u32 intr_mask; int retval; int dev_speed; @@ -386,18 +385,15 @@ static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg, return -ENODEV; } - qtd = kzalloc(sizeof(*qtd), mem_flags); if (!qtd) - return -ENOMEM; + return -EINVAL; dwc2_hcd_qtd_init(qtd, urb); - retval = dwc2_hcd_qtd_add(hsotg, qtd, (struct dwc2_qh **)ep_handle, - mem_flags); + retval = dwc2_hcd_qtd_add(hsotg, qtd, qh); if (retval) { dev_err(hsotg->dev, "DWC OTG HCD URB Enqueue failed adding QTD. Error status %d\n", retval); - kfree(qtd); return retval; } @@ -2445,6 +2441,9 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, u32 tflags = 0; void *buf; unsigned long flags; + struct dwc2_qh *qh; + bool qh_allocated = false; + struct dwc2_qtd *qtd; if (dbg_urb(urb)) { dev_vdbg(hsotg->dev, "DWC OTG HCD URB Enqueue\n"); @@ -2523,15 +2522,32 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, urb->iso_frame_desc[i].length); urb->hcpriv = dwc2_urb; + qh = (struct dwc2_qh *) ep->hcpriv; + /* Create QH for the endpoint if it doesn't exist */ + if (!qh) { + qh = dwc2_hcd_qh_create(hsotg, dwc2_urb, mem_flags); + if (!qh) { + retval = -ENOMEM; + goto fail0; + } + ep->hcpriv = qh; + qh_allocated = true; + } + + qtd = kzalloc(sizeof(*qtd), mem_flags); + if (!qtd) { + retval = -ENOMEM; + goto fail1; + } spin_lock_irqsave(&hsotg->lock, flags); retval = usb_hcd_link_urb_to_ep(hcd, urb); if (retval) - goto fail1; + goto fail2; - retval = dwc2_hcd_urb_enqueue(hsotg, dwc2_urb, &ep->hcpriv, mem_flags); + retval = dwc2_hcd_urb_enqueue(hsotg, dwc2_urb, qh, qtd); if (retval) - goto fail2; + goto fail3; if (alloc_bandwidth) { dwc2_allocate_bus_bandwidth(hcd, @@ -2543,12 +2559,25 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, return 0; -fail2: +fail3: dwc2_urb->priv = NULL; usb_hcd_unlink_urb_from_ep(hcd, urb); -fail1: +fail2: spin_unlock_irqrestore(&hsotg->lock, flags); urb->hcpriv = NULL; + kfree(qtd); +fail1: + if (qh_allocated) { + struct dwc2_qtd *qtd2, *qtd2_tmp; + + ep->hcpriv = NULL; + dwc2_hcd_qh_unlink(hsotg, qh); + /* Free each QTD in the QH's QTD list */ + list_for_each_entry_safe(qtd2, qtd2_tmp, &qh->qtd_list, + qtd_list_entry) + dwc2_hcd_qtd_unlink_and_free(hsotg, qtd2, qh); + dwc2_hcd_qh_free(hsotg, qh); + } fail0: kfree(dwc2_urb); diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h index 7b5841c40033..fc1054965552 100644 --- a/drivers/usb/dwc2/hcd.h +++ b/drivers/usb/dwc2/hcd.h @@ -463,6 +463,9 @@ extern void dwc2_hcd_queue_transactions(struct dwc2_hsotg *hsotg, /* Schedule Queue Functions */ /* Implemented in hcd_queue.c */ extern void dwc2_hcd_init_usecs(struct dwc2_hsotg *hsotg); +extern struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg, + struct dwc2_hcd_urb *urb, + gfp_t mem_flags); extern void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh); extern int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh); extern void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh); @@ -471,7 +474,7 @@ extern void dwc2_hcd_qh_deactivate(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, extern void dwc2_hcd_qtd_init(struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb); extern int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, - struct dwc2_qh **qh, gfp_t mem_flags); + struct dwc2_qh *qh); /* Unlinks and frees a QTD */ static inline void dwc2_hcd_qtd_unlink_and_free(struct dwc2_hsotg *hsotg, diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c index 9b5c36256627..3ad63d392e13 100644 --- a/drivers/usb/dwc2/hcd_queue.c +++ b/drivers/usb/dwc2/hcd_queue.c @@ -191,7 +191,7 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, * * Return: Pointer to the newly allocated QH, or NULL on error */ -static struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg, +struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg, struct dwc2_hcd_urb *urb, gfp_t mem_flags) { @@ -767,57 +767,32 @@ void dwc2_hcd_qtd_init(struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb) * * @hsotg: The DWC HCD structure * @qtd: The QTD to add - * @qh: Out parameter to return queue head - * @atomic_alloc: Flag to do atomic alloc if needed + * @qh: Queue head to add qtd to * * Return: 0 if successful, negative error code otherwise * - * Finds the correct QH to place the QTD into. If it does not find a QH, it - * will create a new QH. If the QH to which the QTD is added is not currently - * scheduled, it is placed into the proper schedule based on its EP type. + * If the QH to which the QTD is added is not currently scheduled, it is placed + * into the proper schedule based on its EP type. */ int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, - struct dwc2_qh **qh, gfp_t mem_flags) + struct dwc2_qh *qh) { - struct dwc2_hcd_urb *urb = qtd->urb; - int allocated = 0; int retval; - /* - * Get the QH which holds the QTD-list to insert to. Create QH if it - * doesn't exist. - */ - if (*qh == NULL) { - *qh = dwc2_hcd_qh_create(hsotg, urb, mem_flags); - if (*qh == NULL) - return -ENOMEM; - allocated = 1; + if (unlikely(!qh)) { + dev_err(hsotg->dev, "%s: Invalid QH\n", __func__); + retval = -EINVAL; + goto fail; } - retval = dwc2_hcd_qh_add(hsotg, *qh); + retval = dwc2_hcd_qh_add(hsotg, qh); if (retval) goto fail; - qtd->qh = *qh; - list_add_tail(&qtd->qtd_list_entry, &(*qh)->qtd_list); + qtd->qh = qh; + list_add_tail(&qtd->qtd_list_entry, &qh->qtd_list); return 0; - fail: - if (allocated) { - struct dwc2_qtd *qtd2, *qtd2_tmp; - struct dwc2_qh *qh_tmp = *qh; - - *qh = NULL; - dwc2_hcd_qh_unlink(hsotg, qh_tmp); - - /* Free each QTD in the QH's QTD list */ - list_for_each_entry_safe(qtd2, qtd2_tmp, &qh_tmp->qtd_list, - qtd_list_entry) - dwc2_hcd_qtd_unlink_and_free(hsotg, qtd2, qh_tmp); - - dwc2_hcd_qh_free(hsotg, qh_tmp); - } - return retval; } diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 5c110d8e293b..ff5773c66b84 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -446,10 +446,12 @@ static int dwc3_phy_setup(struct dwc3 *dwc) /* Select the HS PHY interface */ switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) { case DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI: - if (!strncmp(dwc->hsphy_interface, "utmi", 4)) { + if (dwc->hsphy_interface && + !strncmp(dwc->hsphy_interface, "utmi", 4)) { reg &= ~DWC3_GUSB2PHYCFG_ULPI_UTMI; break; - } else if (!strncmp(dwc->hsphy_interface, "ulpi", 4)) { + } else if (dwc->hsphy_interface && + !strncmp(dwc->hsphy_interface, "ulpi", 4)) { reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); } else { diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 2ef3c8d6a9db..69e769c35cf5 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -727,6 +727,10 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ISOCH_DELAY"); ret = dwc3_ep0_set_isoch_delay(dwc, ctrl); break; + case USB_REQ_SET_INTERFACE: + dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_INTERFACE"); + dwc->start_config_issued = false; + /* Fall through */ default: dwc3_trace(trace_dwc3_ep0, "Forwarding to gadget driver"); ret = dwc3_ep0_delegate_req(dwc, ctrl); diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 4e3447bbd097..58b4657fc721 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1758,10 +1758,13 @@ unknown: * take such requests too, if that's ever needed: to work * in config 0, etc. */ - list_for_each_entry(f, &cdev->config->functions, list) - if (f->req_match && f->req_match(f, ctrl)) - goto try_fun_setup; - f = NULL; + if (cdev->config) { + list_for_each_entry(f, &cdev->config->functions, list) + if (f->req_match && f->req_match(f, ctrl)) + goto try_fun_setup; + f = NULL; + } + switch (ctrl->bRequestType & USB_RECIP_MASK) { case USB_RECIP_INTERFACE: if (!cdev->config || intf >= MAX_CONFIG_INTERFACES) diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 0495c94a23d7..289e20119fea 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -571,7 +571,7 @@ static struct config_group *function_make( if (IS_ERR(fi)) return ERR_CAST(fi); - ret = config_item_set_name(&fi->group.cg_item, name); + ret = config_item_set_name(&fi->group.cg_item, "%s", name); if (ret) { usb_put_function_instance(fi); return ERR_PTR(ret); diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 45b8c8b338df..6e7be91e6097 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -924,7 +924,8 @@ static ssize_t ffs_epfile_write_iter(struct kiocb *kiocb, struct iov_iter *from) kiocb->private = p; - kiocb_set_cancel_fn(kiocb, ffs_aio_cancel); + if (p->aio) + kiocb_set_cancel_fn(kiocb, ffs_aio_cancel); res = ffs_epfile_io(kiocb->ki_filp, p); if (res == -EIOCBQUEUED) @@ -968,7 +969,8 @@ static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to) kiocb->private = p; - kiocb_set_cancel_fn(kiocb, ffs_aio_cancel); + if (p->aio) + kiocb_set_cancel_fn(kiocb, ffs_aio_cancel); res = ffs_epfile_io(kiocb->ki_filp, p); if (res == -EIOCBQUEUED) diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c index f7f35a36c09a..6df9715a4bcd 100644 --- a/drivers/usb/gadget/function/f_hid.c +++ b/drivers/usb/gadget/function/f_hid.c @@ -699,6 +699,10 @@ static inline int hidg_get_minor(void) int ret; ret = ida_simple_get(&hidg_ida, 0, 0, GFP_KERNEL); + if (ret >= HIDG_MINORS) { + ida_simple_remove(&hidg_ida, ret); + ret = -ENODEV; + } return ret; } diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index d2259c663996..f936268d26c6 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -2786,7 +2786,7 @@ int fsg_common_set_nluns(struct fsg_common *common, int nluns) return -EINVAL; } - curlun = kcalloc(nluns, sizeof(*curlun), GFP_KERNEL); + curlun = kcalloc(FSG_MAX_LUNS, sizeof(*curlun), GFP_KERNEL); if (unlikely(!curlun)) return -ENOMEM; @@ -2796,8 +2796,6 @@ int fsg_common_set_nluns(struct fsg_common *common, int nluns) common->luns = curlun; common->nluns = nluns; - pr_info("Number of LUNs=%d\n", common->nluns); - return 0; } EXPORT_SYMBOL_GPL(fsg_common_set_nluns); @@ -3563,14 +3561,26 @@ static struct usb_function *fsg_alloc(struct usb_function_instance *fi) struct fsg_opts *opts = fsg_opts_from_func_inst(fi); struct fsg_common *common = opts->common; struct fsg_dev *fsg; + unsigned nluns, i; fsg = kzalloc(sizeof(*fsg), GFP_KERNEL); if (unlikely(!fsg)) return ERR_PTR(-ENOMEM); mutex_lock(&opts->lock); + if (!opts->refcnt) { + for (nluns = i = 0; i < FSG_MAX_LUNS; ++i) + if (common->luns[i]) + nluns = i + 1; + if (!nluns) + pr_warn("No LUNS defined, continuing anyway\n"); + else + common->nluns = nluns; + pr_info("Number of LUNs=%u\n", common->nluns); + } opts->refcnt++; mutex_unlock(&opts->lock); + fsg->function.name = FSG_DRIVER_DESC; fsg->function.bind = fsg_bind; fsg->function.unbind = fsg_unbind; diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index 6316aa5b1c49..ad50a67c1465 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -1145,7 +1145,7 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) if (opts->id && !midi->id) { status = -ENOMEM; mutex_unlock(&opts->lock); - goto kstrdup_fail; + goto setup_fail; } midi->in_ports = opts->in_ports; midi->out_ports = opts->out_ports; @@ -1164,8 +1164,6 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) return &midi->func; -kstrdup_fail: - f_midi_unregister_card(midi); setup_fail: for (--i; i >= 0; i--) kfree(midi->in_port[i]); diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c index 44173df27273..357f63f47b42 100644 --- a/drivers/usb/gadget/function/f_printer.c +++ b/drivers/usb/gadget/function/f_printer.c @@ -1248,7 +1248,15 @@ static struct config_item_type printer_func_type = { static inline int gprinter_get_minor(void) { - return ida_simple_get(&printer_ida, 0, 0, GFP_KERNEL); + int ret; + + ret = ida_simple_get(&printer_ida, 0, 0, GFP_KERNEL); + if (ret >= PRINTER_MINORS) { + ida_simple_remove(&printer_ida, ret); + ret = -ENODEV; + } + + return ret; } static inline void gprinter_put_minor(int minor) diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index 6d3eb8b00a48..531861547253 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c @@ -1162,14 +1162,14 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) factor = 1000; } else { ep_desc = &hs_epin_desc; - factor = 125; + factor = 8000; } /* pre-compute some values for iso_complete() */ uac2->p_framesize = opts->p_ssize * num_channels(opts->p_chmask); rate = opts->p_srate * uac2->p_framesize; - uac2->p_interval = (1 << (ep_desc->bInterval - 1)) * factor; + uac2->p_interval = factor / (1 << (ep_desc->bInterval - 1)); uac2->p_pktsize = min_t(unsigned int, rate / uac2->p_interval, prm->max_psize); diff --git a/drivers/usb/gadget/udc/bdc/bdc_ep.c b/drivers/usb/gadget/udc/bdc/bdc_ep.c index b04980cf6dc4..1efa61265d8d 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_ep.c +++ b/drivers/usb/gadget/udc/bdc/bdc_ep.c @@ -779,7 +779,7 @@ static int ep_dequeue(struct bdc_ep *ep, struct bdc_req *req) /* The current hw dequeue pointer */ tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS0(0)); deq_ptr_64 = tmp_32; - tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS0(1)); + tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS1(0)); deq_ptr_64 |= ((u64)tmp_32 << 32); /* we have the dma addr of next bd that will be fetched by hardware */ diff --git a/drivers/usb/gadget/udc/fotg210-udc.c b/drivers/usb/gadget/udc/fotg210-udc.c index e547ea7f56b1..1137e3384218 100644 --- a/drivers/usb/gadget/udc/fotg210-udc.c +++ b/drivers/usb/gadget/udc/fotg210-udc.c @@ -1171,7 +1171,7 @@ static int fotg210_udc_probe(struct platform_device *pdev) udc_name, fotg210); if (ret < 0) { pr_err("request_irq error (%d)\n", ret); - goto err_irq; + goto err_req; } ret = usb_add_gadget_udc(&pdev->dev, &fotg210->gadget); @@ -1183,7 +1183,6 @@ static int fotg210_udc_probe(struct platform_device *pdev) return 0; err_add_udc: -err_irq: free_irq(ires->start, fotg210); err_req: diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c index d32160d6463f..5da37c957b53 100644 --- a/drivers/usb/gadget/udc/mv_udc_core.c +++ b/drivers/usb/gadget/udc/mv_udc_core.c @@ -2167,7 +2167,7 @@ static int mv_udc_probe(struct platform_device *pdev) return -ENODEV; } - udc->phy_regs = ioremap(r->start, resource_size(r)); + udc->phy_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r)); if (udc->phy_regs == NULL) { dev_err(&pdev->dev, "failed to map phy I/O memory\n"); return -EBUSY; diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c index d69c35558f68..89ed5e71a199 100644 --- a/drivers/usb/gadget/udc/udc-core.c +++ b/drivers/usb/gadget/udc/udc-core.c @@ -60,13 +60,15 @@ static DEFINE_MUTEX(udc_lock); int usb_gadget_map_request(struct usb_gadget *gadget, struct usb_request *req, int is_in) { + struct device *dev = gadget->dev.parent; + if (req->length == 0) return 0; if (req->num_sgs) { int mapped; - mapped = dma_map_sg(&gadget->dev, req->sg, req->num_sgs, + mapped = dma_map_sg(dev, req->sg, req->num_sgs, is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); if (mapped == 0) { dev_err(&gadget->dev, "failed to map SGs\n"); @@ -75,11 +77,11 @@ int usb_gadget_map_request(struct usb_gadget *gadget, req->num_mapped_sgs = mapped; } else { - req->dma = dma_map_single(&gadget->dev, req->buf, req->length, + req->dma = dma_map_single(dev, req->buf, req->length, is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - if (dma_mapping_error(&gadget->dev, req->dma)) { - dev_err(&gadget->dev, "failed to map buffer\n"); + if (dma_mapping_error(dev, req->dma)) { + dev_err(dev, "failed to map buffer\n"); return -EFAULT; } } @@ -95,12 +97,12 @@ void usb_gadget_unmap_request(struct usb_gadget *gadget, return; if (req->num_mapped_sgs) { - dma_unmap_sg(&gadget->dev, req->sg, req->num_mapped_sgs, + dma_unmap_sg(gadget->dev.parent, req->sg, req->num_mapped_sgs, is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); req->num_mapped_sgs = 0; } else { - dma_unmap_single(&gadget->dev, req->dma, req->length, + dma_unmap_single(gadget->dev.parent, req->dma, req->length, is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); } } @@ -321,6 +323,7 @@ err4: err3: put_device(&udc->dev); + device_del(&gadget->dev); err2: put_device(&gadget->dev); diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index f7d561ed3c23..d029bbe9eb36 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -981,10 +981,6 @@ rescan_all: int completed, modified; __hc32 *prev; - /* Is this ED already invisible to the hardware? */ - if (ed->state == ED_IDLE) - goto ed_idle; - /* only take off EDs that the HC isn't using, accounting for * frame counter wraps and EDs with partially retired TDs */ @@ -1012,12 +1008,10 @@ skip_ed: } /* ED's now officially unlinked, hc doesn't see */ - ed->state = ED_IDLE; ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H); ed->hwNextED = 0; wmb(); ed->hwINFO &= ~cpu_to_hc32(ohci, ED_SKIP | ED_DEQUEUE); -ed_idle: /* reentrancy: if we drop the schedule lock, someone might * have modified this list. normally it's just prepending @@ -1088,6 +1082,7 @@ rescan_this: if (list_empty(&ed->td_list)) { *last = ed->ed_next; ed->ed_next = NULL; + ed->state = ED_IDLE; list_del(&ed->in_use_list); } else if (ohci->rh_state == OHCI_RH_RUNNING) { *last = ed->ed_next; diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c index e9a6eec39142..cfcfadfc94fc 100644 --- a/drivers/usb/host/ohci-tmio.c +++ b/drivers/usb/host/ohci-tmio.c @@ -58,7 +58,7 @@ #define CCR_PM_CKRNEN 0x0002 #define CCR_PM_USBPW1 0x0004 #define CCR_PM_USBPW2 0x0008 -#define CCR_PM_USBPW3 0x0008 +#define CCR_PM_USBPW3 0x0010 #define CCR_PM_PMEE 0x0100 #define CCR_PM_PMES 0x8000 diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index e75c565feb53..78241b5550df 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -484,10 +484,13 @@ static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci, u32 pls = status_reg & PORT_PLS_MASK; /* resume state is a xHCI internal state. - * Do not report it to usb core. + * Do not report it to usb core, instead, pretend to be U3, + * thus usb core knows it's not ready for transfer */ - if (pls == XDEV_RESUME) + if (pls == XDEV_RESUME) { + *status |= USB_SS_PORT_LS_U3; return; + } /* When the CAS bit is set then warm reset * should be performed on port @@ -588,7 +591,14 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, status |= USB_PORT_STAT_C_RESET << 16; /* USB3.0 only */ if (hcd->speed == HCD_USB3) { - if ((raw_port_status & PORT_PLC)) + /* Port link change with port in resume state should not be + * reported to usbcore, as this is an internal state to be + * handled by xhci driver. Reporting PLC to usbcore may + * cause usbcore clearing PLC first and port change event + * irq won't be generated. + */ + if ((raw_port_status & PORT_PLC) && + (raw_port_status & PORT_PLS_MASK) != XDEV_RESUME) status |= USB_PORT_STAT_C_LINK_STATE << 16; if ((raw_port_status & PORT_WRC)) status |= USB_PORT_STAT_C_BH_RESET << 16; @@ -1120,10 +1130,10 @@ int xhci_bus_suspend(struct usb_hcd *hcd) spin_lock_irqsave(&xhci->lock, flags); if (hcd->self.root_hub->do_remote_wakeup) { - if (bus_state->resuming_ports) { + if (bus_state->resuming_ports || /* USB2 */ + bus_state->port_remote_wakeup) { /* USB3 */ spin_unlock_irqrestore(&xhci->lock, flags); - xhci_dbg(xhci, "suspend failed because " - "a port is resuming\n"); + xhci_dbg(xhci, "suspend failed because a port is resuming\n"); return -EBUSY; } } diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index f8336408ef07..9a8c936cd42c 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1427,10 +1427,10 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, /* Attempt to use the ring cache */ if (virt_dev->num_rings_cached == 0) return -ENOMEM; + virt_dev->num_rings_cached--; virt_dev->eps[ep_index].new_ring = virt_dev->ring_cache[virt_dev->num_rings_cached]; virt_dev->ring_cache[virt_dev->num_rings_cached] = NULL; - virt_dev->num_rings_cached--; xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring, 1, type); } @@ -1792,7 +1792,8 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) int size; int i, j, num_ports; - del_timer_sync(&xhci->cmd_timer); + if (timer_pending(&xhci->cmd_timer)) + del_timer_sync(&xhci->cmd_timer); /* Free the Event Ring Segment Table and the actual Event Ring */ size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries); diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 4a4cb1d91ac8..5590eac2b22d 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -23,10 +23,15 @@ #include <linux/pci.h> #include <linux/slab.h> #include <linux/module.h> +#include <linux/acpi.h> #include "xhci.h" #include "xhci-trace.h" +#define PORT2_SSIC_CONFIG_REG2 0x883c +#define PROG_DONE (1 << 30) +#define SSIC_PORT_UNUSED (1 << 31) + /* Device for a quirk */ #define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73 #define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000 @@ -176,20 +181,63 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) } /* + * In some Intel xHCI controllers, in order to get D3 working, + * through a vendor specific SSIC CONFIG register at offset 0x883c, + * SSIC PORT need to be marked as "unused" before putting xHCI + * into D3. After D3 exit, the SSIC port need to be marked as "used". + * Without this change, xHCI might not enter D3 state. * Make sure PME works on some Intel xHCI controllers by writing 1 to clear * the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4 */ -static void xhci_pme_quirk(struct xhci_hcd *xhci) +static void xhci_pme_quirk(struct usb_hcd *hcd, bool suspend) { + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); u32 val; void __iomem *reg; + if (pdev->vendor == PCI_VENDOR_ID_INTEL && + pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) { + + reg = (void __iomem *) xhci->cap_regs + PORT2_SSIC_CONFIG_REG2; + + /* Notify SSIC that SSIC profile programming is not done */ + val = readl(reg) & ~PROG_DONE; + writel(val, reg); + + /* Mark SSIC port as unused(suspend) or used(resume) */ + val = readl(reg); + if (suspend) + val |= SSIC_PORT_UNUSED; + else + val &= ~SSIC_PORT_UNUSED; + writel(val, reg); + + /* Notify SSIC that SSIC profile programming is done */ + val = readl(reg) | PROG_DONE; + writel(val, reg); + readl(reg); + } + reg = (void __iomem *) xhci->cap_regs + 0x80a4; val = readl(reg); writel(val | BIT(28), reg); readl(reg); } +#ifdef CONFIG_ACPI +static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) +{ + static const u8 intel_dsm_uuid[] = { + 0xb7, 0x0c, 0x34, 0xac, 0x01, 0xe9, 0xbf, 0x45, + 0xb7, 0xe6, 0x2b, 0x34, 0xec, 0x93, 0x1e, 0x23, + }; + acpi_evaluate_dsm(ACPI_HANDLE(&dev->dev), intel_dsm_uuid, 3, 1, NULL); +} +#else + static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) { } +#endif /* CONFIG_ACPI */ + /* called during probe() after chip reset completes */ static int xhci_pci_setup(struct usb_hcd *hcd) { @@ -263,6 +311,9 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) HCC_MAX_PSA(xhci->hcc_params) >= 4) xhci->shared_hcd->can_do_streams = 1; + if (xhci->quirks & XHCI_PME_STUCK_QUIRK) + xhci_pme_acpi_rtd3_enable(dev); + /* USB-2 and USB-3 roothubs initialized, allow runtime pm suspend */ pm_runtime_put_noidle(&dev->dev); @@ -307,7 +358,7 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) pdev->no_d3cold = true; if (xhci->quirks & XHCI_PME_STUCK_QUIRK) - xhci_pme_quirk(xhci); + xhci_pme_quirk(hcd, true); return xhci_suspend(xhci, do_wakeup); } @@ -340,7 +391,7 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated) usb_enable_intel_xhci_ports(pdev); if (xhci->quirks & XHCI_PME_STUCK_QUIRK) - xhci_pme_quirk(xhci); + xhci_pme_quirk(hcd, false); retval = xhci_resume(xhci, hibernated); return retval; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 94416ff70810..32f4d564494a 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -82,7 +82,7 @@ dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, return 0; /* offset in TRBs */ segment_offset = trb - seg->trbs; - if (segment_offset > TRBS_PER_SEGMENT) + if (segment_offset >= TRBS_PER_SEGMENT) return 0; return seg->dma + (segment_offset * sizeof(*trb)); } @@ -1546,6 +1546,9 @@ static void handle_port_status(struct xhci_hcd *xhci, usb_hcd_resume_root_hub(hcd); } + if (hcd->speed == HCD_USB3 && (temp & PORT_PLS_MASK) == XDEV_INACTIVE) + bus_state->port_remote_wakeup &= ~(1 << faked_port_index); + if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_RESUME) { xhci_dbg(xhci, "port resume event for port %d\n", port_id); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 7da0d6043d33..526ebc0c7e72 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3453,6 +3453,9 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) return -EINVAL; } + if (virt_dev->tt_info) + old_active_eps = virt_dev->tt_info->active_eps; + if (virt_dev->udev != udev) { /* If the virt_dev and the udev does not match, this virt_dev * may belong to another udev. diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 31e46cc55807..ed2ebf647c38 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -285,6 +285,7 @@ struct xhci_op_regs { #define XDEV_U0 (0x0 << 5) #define XDEV_U2 (0x2 << 5) #define XDEV_U3 (0x3 << 5) +#define XDEV_INACTIVE (0x6 << 5) #define XDEV_RESUME (0xf << 5) /* true: port has power (see HCC_PPC) */ #define PORT_POWER (1 << 9) diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index 30842bc195f5..92d5f718659b 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -275,9 +275,7 @@ static int musb_has_gadget(struct musb *musb) #ifdef CONFIG_USB_MUSB_HOST return 1; #else - if (musb->port_mode == MUSB_PORT_MODE_HOST) - return 1; - return musb->g.dev.driver != NULL; + return musb->port_mode == MUSB_PORT_MODE_HOST; #endif } diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c index 8f7cb068d29b..3fcc0483a081 100644 --- a/drivers/usb/phy/phy-mxs-usb.c +++ b/drivers/usb/phy/phy-mxs-usb.c @@ -217,6 +217,9 @@ static bool mxs_phy_get_vbus_status(struct mxs_phy *mxs_phy) { unsigned int vbus_value; + if (!mxs_phy->regmap_anatop) + return false; + if (mxs_phy->port_id == 0) regmap_read(mxs_phy->regmap_anatop, ANADIG_USB1_VBUS_DET_STAT, diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index ffd739e31bfc..eac7ccaa3c85 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -187,6 +187,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x1FB9, 0x0602) }, /* Lake Shore Model 648 Magnet Power Supply */ { USB_DEVICE(0x1FB9, 0x0700) }, /* Lake Shore Model 737 VSM Controller */ { USB_DEVICE(0x1FB9, 0x0701) }, /* Lake Shore Model 776 Hall Matrix */ + { USB_DEVICE(0x2626, 0xEA60) }, /* Aruba Networks 7xxx USB Serial Console */ { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */ { USB_DEVICE(0x3195, 0xF280) }, /* Link Instruments MSO-28 */ { USB_DEVICE(0x3195, 0xF281) }, /* Link Instruments MSO-28 */ diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 4f70df33975a..78b4f64c6b00 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -121,26 +121,26 @@ static DEFINE_SPINLOCK(release_lock); static const unsigned int dummy; /* for clarity in register access fns */ enum mos_regs { - THR, /* serial port regs */ - RHR, - IER, - FCR, - ISR, - LCR, - MCR, - LSR, - MSR, - SPR, - DLL, - DLM, - DPR, /* parallel port regs */ - DSR, - DCR, - ECR, - SP1_REG, /* device control regs */ - SP2_REG, /* serial port 2 (7720 only) */ - PP_REG, - SP_CONTROL_REG, + MOS7720_THR, /* serial port regs */ + MOS7720_RHR, + MOS7720_IER, + MOS7720_FCR, + MOS7720_ISR, + MOS7720_LCR, + MOS7720_MCR, + MOS7720_LSR, + MOS7720_MSR, + MOS7720_SPR, + MOS7720_DLL, + MOS7720_DLM, + MOS7720_DPR, /* parallel port regs */ + MOS7720_DSR, + MOS7720_DCR, + MOS7720_ECR, + MOS7720_SP1_REG, /* device control regs */ + MOS7720_SP2_REG, /* serial port 2 (7720 only) */ + MOS7720_PP_REG, + MOS7720_SP_CONTROL_REG, }; /* @@ -150,26 +150,26 @@ enum mos_regs { static inline __u16 get_reg_index(enum mos_regs reg) { static const __u16 mos7715_index_lookup_table[] = { - 0x00, /* THR */ - 0x00, /* RHR */ - 0x01, /* IER */ - 0x02, /* FCR */ - 0x02, /* ISR */ - 0x03, /* LCR */ - 0x04, /* MCR */ - 0x05, /* LSR */ - 0x06, /* MSR */ - 0x07, /* SPR */ - 0x00, /* DLL */ - 0x01, /* DLM */ - 0x00, /* DPR */ - 0x01, /* DSR */ - 0x02, /* DCR */ - 0x0a, /* ECR */ - 0x01, /* SP1_REG */ - 0x02, /* SP2_REG (7720 only) */ - 0x04, /* PP_REG (7715 only) */ - 0x08, /* SP_CONTROL_REG */ + 0x00, /* MOS7720_THR */ + 0x00, /* MOS7720_RHR */ + 0x01, /* MOS7720_IER */ + 0x02, /* MOS7720_FCR */ + 0x02, /* MOS7720_ISR */ + 0x03, /* MOS7720_LCR */ + 0x04, /* MOS7720_MCR */ + 0x05, /* MOS7720_LSR */ + 0x06, /* MOS7720_MSR */ + 0x07, /* MOS7720_SPR */ + 0x00, /* MOS7720_DLL */ + 0x01, /* MOS7720_DLM */ + 0x00, /* MOS7720_DPR */ + 0x01, /* MOS7720_DSR */ + 0x02, /* MOS7720_DCR */ + 0x0a, /* MOS7720_ECR */ + 0x01, /* MOS7720_SP1_REG */ + 0x02, /* MOS7720_SP2_REG (7720 only) */ + 0x04, /* MOS7720_PP_REG (7715 only) */ + 0x08, /* MOS7720_SP_CONTROL_REG */ }; return mos7715_index_lookup_table[reg]; } @@ -181,10 +181,10 @@ static inline __u16 get_reg_index(enum mos_regs reg) static inline __u16 get_reg_value(enum mos_regs reg, unsigned int serial_portnum) { - if (reg >= SP1_REG) /* control reg */ + if (reg >= MOS7720_SP1_REG) /* control reg */ return 0x0000; - else if (reg >= DPR) /* parallel port reg (7715 only) */ + else if (reg >= MOS7720_DPR) /* parallel port reg (7715 only) */ return 0x0100; else /* serial port reg */ @@ -252,7 +252,8 @@ static inline int mos7715_change_mode(struct mos7715_parport *mos_parport, enum mos7715_pp_modes mode) { mos_parport->shadowECR = mode; - write_mos_reg(mos_parport->serial, dummy, ECR, mos_parport->shadowECR); + write_mos_reg(mos_parport->serial, dummy, MOS7720_ECR, + mos_parport->shadowECR); return 0; } @@ -486,7 +487,7 @@ static void parport_mos7715_write_data(struct parport *pp, unsigned char d) if (parport_prologue(pp) < 0) return; mos7715_change_mode(mos_parport, SPP); - write_mos_reg(mos_parport->serial, dummy, DPR, (__u8)d); + write_mos_reg(mos_parport->serial, dummy, MOS7720_DPR, (__u8)d); parport_epilogue(pp); } @@ -497,7 +498,7 @@ static unsigned char parport_mos7715_read_data(struct parport *pp) if (parport_prologue(pp) < 0) return 0; - read_mos_reg(mos_parport->serial, dummy, DPR, &d); + read_mos_reg(mos_parport->serial, dummy, MOS7720_DPR, &d); parport_epilogue(pp); return d; } @@ -510,7 +511,7 @@ static void parport_mos7715_write_control(struct parport *pp, unsigned char d) if (parport_prologue(pp) < 0) return; data = ((__u8)d & 0x0f) | (mos_parport->shadowDCR & 0xf0); - write_mos_reg(mos_parport->serial, dummy, DCR, data); + write_mos_reg(mos_parport->serial, dummy, MOS7720_DCR, data); mos_parport->shadowDCR = data; parport_epilogue(pp); } @@ -543,7 +544,8 @@ static unsigned char parport_mos7715_frob_control(struct parport *pp, if (parport_prologue(pp) < 0) return 0; mos_parport->shadowDCR = (mos_parport->shadowDCR & (~mask)) ^ val; - write_mos_reg(mos_parport->serial, dummy, DCR, mos_parport->shadowDCR); + write_mos_reg(mos_parport->serial, dummy, MOS7720_DCR, + mos_parport->shadowDCR); dcr = mos_parport->shadowDCR & 0x0f; parport_epilogue(pp); return dcr; @@ -581,7 +583,8 @@ static void parport_mos7715_data_forward(struct parport *pp) return; mos7715_change_mode(mos_parport, PS2); mos_parport->shadowDCR &= ~0x20; - write_mos_reg(mos_parport->serial, dummy, DCR, mos_parport->shadowDCR); + write_mos_reg(mos_parport->serial, dummy, MOS7720_DCR, + mos_parport->shadowDCR); parport_epilogue(pp); } @@ -593,7 +596,8 @@ static void parport_mos7715_data_reverse(struct parport *pp) return; mos7715_change_mode(mos_parport, PS2); mos_parport->shadowDCR |= 0x20; - write_mos_reg(mos_parport->serial, dummy, DCR, mos_parport->shadowDCR); + write_mos_reg(mos_parport->serial, dummy, MOS7720_DCR, + mos_parport->shadowDCR); parport_epilogue(pp); } @@ -633,8 +637,10 @@ static void parport_mos7715_restore_state(struct parport *pp, spin_unlock(&release_lock); return; } - write_parport_reg_nonblock(mos_parport, DCR, mos_parport->shadowDCR); - write_parport_reg_nonblock(mos_parport, ECR, mos_parport->shadowECR); + write_parport_reg_nonblock(mos_parport, MOS7720_DCR, + mos_parport->shadowDCR); + write_parport_reg_nonblock(mos_parport, MOS7720_ECR, + mos_parport->shadowECR); spin_unlock(&release_lock); } @@ -714,14 +720,16 @@ static int mos7715_parport_init(struct usb_serial *serial) init_completion(&mos_parport->syncmsg_compl); /* cycle parallel port reset bit */ - write_mos_reg(mos_parport->serial, dummy, PP_REG, (__u8)0x80); - write_mos_reg(mos_parport->serial, dummy, PP_REG, (__u8)0x00); + write_mos_reg(mos_parport->serial, dummy, MOS7720_PP_REG, (__u8)0x80); + write_mos_reg(mos_parport->serial, dummy, MOS7720_PP_REG, (__u8)0x00); /* initialize device registers */ mos_parport->shadowDCR = DCR_INIT_VAL; - write_mos_reg(mos_parport->serial, dummy, DCR, mos_parport->shadowDCR); + write_mos_reg(mos_parport->serial, dummy, MOS7720_DCR, + mos_parport->shadowDCR); mos_parport->shadowECR = ECR_INIT_VAL; - write_mos_reg(mos_parport->serial, dummy, ECR, mos_parport->shadowECR); + write_mos_reg(mos_parport->serial, dummy, MOS7720_ECR, + mos_parport->shadowECR); /* register with parport core */ mos_parport->pp = parport_register_port(0, PARPORT_IRQ_NONE, @@ -1033,45 +1041,49 @@ static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port) /* Initialize MCS7720 -- Write Init values to corresponding Registers * * Register Index - * 0 : THR/RHR - * 1 : IER - * 2 : FCR - * 3 : LCR - * 4 : MCR - * 5 : LSR - * 6 : MSR - * 7 : SPR + * 0 : MOS7720_THR/MOS7720_RHR + * 1 : MOS7720_IER + * 2 : MOS7720_FCR + * 3 : MOS7720_LCR + * 4 : MOS7720_MCR + * 5 : MOS7720_LSR + * 6 : MOS7720_MSR + * 7 : MOS7720_SPR * * 0x08 : SP1/2 Control Reg */ port_number = port->port_number; - read_mos_reg(serial, port_number, LSR, &data); + read_mos_reg(serial, port_number, MOS7720_LSR, &data); dev_dbg(&port->dev, "SS::%p LSR:%x\n", mos7720_port, data); - write_mos_reg(serial, dummy, SP1_REG, 0x02); - write_mos_reg(serial, dummy, SP2_REG, 0x02); + write_mos_reg(serial, dummy, MOS7720_SP1_REG, 0x02); + write_mos_reg(serial, dummy, MOS7720_SP2_REG, 0x02); - write_mos_reg(serial, port_number, IER, 0x00); - write_mos_reg(serial, port_number, FCR, 0x00); + write_mos_reg(serial, port_number, MOS7720_IER, 0x00); + write_mos_reg(serial, port_number, MOS7720_FCR, 0x00); - write_mos_reg(serial, port_number, FCR, 0xcf); + write_mos_reg(serial, port_number, MOS7720_FCR, 0xcf); mos7720_port->shadowLCR = 0x03; - write_mos_reg(serial, port_number, LCR, mos7720_port->shadowLCR); + write_mos_reg(serial, port_number, MOS7720_LCR, + mos7720_port->shadowLCR); mos7720_port->shadowMCR = 0x0b; - write_mos_reg(serial, port_number, MCR, mos7720_port->shadowMCR); + write_mos_reg(serial, port_number, MOS7720_MCR, + mos7720_port->shadowMCR); - write_mos_reg(serial, port_number, SP_CONTROL_REG, 0x00); - read_mos_reg(serial, dummy, SP_CONTROL_REG, &data); + write_mos_reg(serial, port_number, MOS7720_SP_CONTROL_REG, 0x00); + read_mos_reg(serial, dummy, MOS7720_SP_CONTROL_REG, &data); data = data | (port->port_number + 1); - write_mos_reg(serial, dummy, SP_CONTROL_REG, data); + write_mos_reg(serial, dummy, MOS7720_SP_CONTROL_REG, data); mos7720_port->shadowLCR = 0x83; - write_mos_reg(serial, port_number, LCR, mos7720_port->shadowLCR); - write_mos_reg(serial, port_number, THR, 0x0c); - write_mos_reg(serial, port_number, IER, 0x00); + write_mos_reg(serial, port_number, MOS7720_LCR, + mos7720_port->shadowLCR); + write_mos_reg(serial, port_number, MOS7720_THR, 0x0c); + write_mos_reg(serial, port_number, MOS7720_IER, 0x00); mos7720_port->shadowLCR = 0x03; - write_mos_reg(serial, port_number, LCR, mos7720_port->shadowLCR); - write_mos_reg(serial, port_number, IER, 0x0c); + write_mos_reg(serial, port_number, MOS7720_LCR, + mos7720_port->shadowLCR); + write_mos_reg(serial, port_number, MOS7720_IER, 0x0c); response = usb_submit_urb(port->read_urb, GFP_KERNEL); if (response) @@ -1144,8 +1156,8 @@ static void mos7720_close(struct usb_serial_port *port) usb_kill_urb(port->write_urb); usb_kill_urb(port->read_urb); - write_mos_reg(serial, port->port_number, MCR, 0x00); - write_mos_reg(serial, port->port_number, IER, 0x00); + write_mos_reg(serial, port->port_number, MOS7720_MCR, 0x00); + write_mos_reg(serial, port->port_number, MOS7720_IER, 0x00); mos7720_port->open = 0; } @@ -1169,7 +1181,8 @@ static void mos7720_break(struct tty_struct *tty, int break_state) data = mos7720_port->shadowLCR & ~UART_LCR_SBC; mos7720_port->shadowLCR = data; - write_mos_reg(serial, port->port_number, LCR, mos7720_port->shadowLCR); + write_mos_reg(serial, port->port_number, MOS7720_LCR, + mos7720_port->shadowLCR); } /* @@ -1297,7 +1310,7 @@ static void mos7720_throttle(struct tty_struct *tty) /* if we are implementing RTS/CTS, toggle that line */ if (tty->termios.c_cflag & CRTSCTS) { mos7720_port->shadowMCR &= ~UART_MCR_RTS; - write_mos_reg(port->serial, port->port_number, MCR, + write_mos_reg(port->serial, port->port_number, MOS7720_MCR, mos7720_port->shadowMCR); } } @@ -1327,7 +1340,7 @@ static void mos7720_unthrottle(struct tty_struct *tty) /* if we are implementing RTS/CTS, toggle that line */ if (tty->termios.c_cflag & CRTSCTS) { mos7720_port->shadowMCR |= UART_MCR_RTS; - write_mos_reg(port->serial, port->port_number, MCR, + write_mos_reg(port->serial, port->port_number, MOS7720_MCR, mos7720_port->shadowMCR); } } @@ -1352,35 +1365,39 @@ static int set_higher_rates(struct moschip_port *mos7720_port, dev_dbg(&port->dev, "Sending Setting Commands ..........\n"); port_number = port->port_number; - write_mos_reg(serial, port_number, IER, 0x00); - write_mos_reg(serial, port_number, FCR, 0x00); - write_mos_reg(serial, port_number, FCR, 0xcf); + write_mos_reg(serial, port_number, MOS7720_IER, 0x00); + write_mos_reg(serial, port_number, MOS7720_FCR, 0x00); + write_mos_reg(serial, port_number, MOS7720_FCR, 0xcf); mos7720_port->shadowMCR = 0x0b; - write_mos_reg(serial, port_number, MCR, mos7720_port->shadowMCR); - write_mos_reg(serial, dummy, SP_CONTROL_REG, 0x00); + write_mos_reg(serial, port_number, MOS7720_MCR, + mos7720_port->shadowMCR); + write_mos_reg(serial, dummy, MOS7720_SP_CONTROL_REG, 0x00); /*********************************************** * Set for higher rates * ***********************************************/ /* writing baud rate verbatum into uart clock field clearly not right */ if (port_number == 0) - sp_reg = SP1_REG; + sp_reg = MOS7720_SP1_REG; else - sp_reg = SP2_REG; + sp_reg = MOS7720_SP2_REG; write_mos_reg(serial, dummy, sp_reg, baud * 0x10); - write_mos_reg(serial, dummy, SP_CONTROL_REG, 0x03); + write_mos_reg(serial, dummy, MOS7720_SP_CONTROL_REG, 0x03); mos7720_port->shadowMCR = 0x2b; - write_mos_reg(serial, port_number, MCR, mos7720_port->shadowMCR); + write_mos_reg(serial, port_number, MOS7720_MCR, + mos7720_port->shadowMCR); /*********************************************** * Set DLL/DLM ***********************************************/ mos7720_port->shadowLCR = mos7720_port->shadowLCR | UART_LCR_DLAB; - write_mos_reg(serial, port_number, LCR, mos7720_port->shadowLCR); - write_mos_reg(serial, port_number, DLL, 0x01); - write_mos_reg(serial, port_number, DLM, 0x00); + write_mos_reg(serial, port_number, MOS7720_LCR, + mos7720_port->shadowLCR); + write_mos_reg(serial, port_number, MOS7720_DLL, 0x01); + write_mos_reg(serial, port_number, MOS7720_DLM, 0x00); mos7720_port->shadowLCR = mos7720_port->shadowLCR & ~UART_LCR_DLAB; - write_mos_reg(serial, port_number, LCR, mos7720_port->shadowLCR); + write_mos_reg(serial, port_number, MOS7720_LCR, + mos7720_port->shadowLCR); return 0; } @@ -1488,15 +1505,16 @@ static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port, /* Enable access to divisor latch */ mos7720_port->shadowLCR = mos7720_port->shadowLCR | UART_LCR_DLAB; - write_mos_reg(serial, number, LCR, mos7720_port->shadowLCR); + write_mos_reg(serial, number, MOS7720_LCR, mos7720_port->shadowLCR); /* Write the divisor */ - write_mos_reg(serial, number, DLL, (__u8)(divisor & 0xff)); - write_mos_reg(serial, number, DLM, (__u8)((divisor & 0xff00) >> 8)); + write_mos_reg(serial, number, MOS7720_DLL, (__u8)(divisor & 0xff)); + write_mos_reg(serial, number, MOS7720_DLM, + (__u8)((divisor & 0xff00) >> 8)); /* Disable access to divisor latch */ mos7720_port->shadowLCR = mos7720_port->shadowLCR & ~UART_LCR_DLAB; - write_mos_reg(serial, number, LCR, mos7720_port->shadowLCR); + write_mos_reg(serial, number, MOS7720_LCR, mos7720_port->shadowLCR); return status; } @@ -1600,14 +1618,16 @@ static void change_port_settings(struct tty_struct *tty, /* Disable Interrupts */ - write_mos_reg(serial, port_number, IER, 0x00); - write_mos_reg(serial, port_number, FCR, 0x00); - write_mos_reg(serial, port_number, FCR, 0xcf); + write_mos_reg(serial, port_number, MOS7720_IER, 0x00); + write_mos_reg(serial, port_number, MOS7720_FCR, 0x00); + write_mos_reg(serial, port_number, MOS7720_FCR, 0xcf); /* Send the updated LCR value to the mos7720 */ - write_mos_reg(serial, port_number, LCR, mos7720_port->shadowLCR); + write_mos_reg(serial, port_number, MOS7720_LCR, + mos7720_port->shadowLCR); mos7720_port->shadowMCR = 0x0b; - write_mos_reg(serial, port_number, MCR, mos7720_port->shadowMCR); + write_mos_reg(serial, port_number, MOS7720_MCR, + mos7720_port->shadowMCR); /* set up the MCR register and send it to the mos7720 */ mos7720_port->shadowMCR = UART_MCR_OUT2; @@ -1619,14 +1639,17 @@ static void change_port_settings(struct tty_struct *tty, /* To set hardware flow control to the specified * * serial port, in SP1/2_CONTROL_REG */ if (port_number) - write_mos_reg(serial, dummy, SP_CONTROL_REG, 0x01); + write_mos_reg(serial, dummy, MOS7720_SP_CONTROL_REG, + 0x01); else - write_mos_reg(serial, dummy, SP_CONTROL_REG, 0x02); + write_mos_reg(serial, dummy, MOS7720_SP_CONTROL_REG, + 0x02); } else mos7720_port->shadowMCR &= ~(UART_MCR_XONANY); - write_mos_reg(serial, port_number, MCR, mos7720_port->shadowMCR); + write_mos_reg(serial, port_number, MOS7720_MCR, + mos7720_port->shadowMCR); /* Determine divisor based on baud rate */ baud = tty_get_baud_rate(tty); @@ -1639,7 +1662,7 @@ static void change_port_settings(struct tty_struct *tty, if (baud >= 230400) { set_higher_rates(mos7720_port, baud); /* Enable Interrupts */ - write_mos_reg(serial, port_number, IER, 0x0c); + write_mos_reg(serial, port_number, MOS7720_IER, 0x0c); return; } @@ -1650,7 +1673,7 @@ static void change_port_settings(struct tty_struct *tty, if (cflag & CBAUD) tty_encode_baud_rate(tty, baud, baud); /* Enable Interrupts */ - write_mos_reg(serial, port_number, IER, 0x0c); + write_mos_reg(serial, port_number, MOS7720_IER, 0x0c); if (port->read_urb->status != -EINPROGRESS) { status = usb_submit_urb(port->read_urb, GFP_KERNEL); @@ -1725,7 +1748,7 @@ static int get_lsr_info(struct tty_struct *tty, count = mos7720_chars_in_buffer(tty); if (count == 0) { - read_mos_reg(port->serial, port_number, LSR, &data); + read_mos_reg(port->serial, port_number, MOS7720_LSR, &data); if ((data & (UART_LSR_TEMT | UART_LSR_THRE)) == (UART_LSR_TEMT | UART_LSR_THRE)) { dev_dbg(&port->dev, "%s -- Empty\n", __func__); @@ -1782,7 +1805,7 @@ static int mos7720_tiocmset(struct tty_struct *tty, mcr &= ~UART_MCR_LOOP; mos7720_port->shadowMCR = mcr; - write_mos_reg(port->serial, port->port_number, MCR, + write_mos_reg(port->serial, port->port_number, MOS7720_MCR, mos7720_port->shadowMCR); return 0; @@ -1827,7 +1850,7 @@ static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd, } mos7720_port->shadowMCR = mcr; - write_mos_reg(port->serial, port->port_number, MCR, + write_mos_reg(port->serial, port->port_number, MOS7720_MCR, mos7720_port->shadowMCR); return 0; @@ -1942,7 +1965,7 @@ static int mos7720_startup(struct usb_serial *serial) } #endif /* LSR For Port 1 */ - read_mos_reg(serial, 0, LSR, &data); + read_mos_reg(serial, 0, MOS7720_LSR, &data); dev_dbg(&dev->dev, "LSR:%x\n", data); return 0; diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index f0c0c53359ad..876423b8892c 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1099,6 +1099,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */ { USB_DEVICE_INTERFACE_CLASS(SIERRA_VENDOR_ID, 0x68c0, 0xff), .driver_info = (kernel_ulong_t)&sierra_mc73xx_blacklist }, /* MC73xx */ + { USB_DEVICE_INTERFACE_CLASS(SIERRA_VENDOR_ID, 0x9041, 0xff), + .driver_info = (kernel_ulong_t)&sierra_mc73xx_blacklist }, /* MC7305/MC7355 */ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003), @@ -1765,6 +1767,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */ { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */ + { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x4000, 0xff) }, /* OLICARD300 - MT6225 */ { USB_DEVICE(INOVIA_VENDOR_ID, INOVIA_SEW858) }, { USB_DEVICE(VIATELECOM_VENDOR_ID, VIATELECOM_PRODUCT_CDS7) }, { } /* Terminating entry */ diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 9c63897b3a56..d156545728c2 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -145,7 +145,6 @@ static const struct usb_device_id id_table[] = { {DEVICE_SWI(0x1199, 0x901c)}, /* Sierra Wireless EM7700 */ {DEVICE_SWI(0x1199, 0x901f)}, /* Sierra Wireless EM7355 */ {DEVICE_SWI(0x1199, 0x9040)}, /* Sierra Wireless Modem */ - {DEVICE_SWI(0x1199, 0x9041)}, /* Sierra Wireless MC7305/MC7355 */ {DEVICE_SWI(0x1199, 0x9051)}, /* Netgear AirCard 340U */ {DEVICE_SWI(0x1199, 0x9053)}, /* Sierra Wireless Modem */ {DEVICE_SWI(0x1199, 0x9054)}, /* Sierra Wireless Modem */ @@ -158,6 +157,7 @@ static const struct usb_device_id id_table[] = { {DEVICE_SWI(0x413c, 0x81a4)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */ {DEVICE_SWI(0x413c, 0x81a8)}, /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */ {DEVICE_SWI(0x413c, 0x81a9)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */ + {DEVICE_SWI(0x413c, 0x81b1)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */ /* Huawei devices */ {DEVICE_HWI(0x03f0, 0x581d)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Modem (Huawei me906e) */ diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 46179a0828eb..07d1ecd564f7 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -289,6 +289,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68AA, 0xFF, 0xFF, 0xFF), .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist }, + { USB_DEVICE(0x1199, 0x68AB) }, /* Sierra Wireless AR8550 */ /* AT&T Direct IP LTE modems */ { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68AA, 0xFF, 0xFF, 0xFF), .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 529066bbc7e8..46f1f13b41f1 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1306,6 +1306,7 @@ static void __exit usb_serial_exit(void) tty_unregister_driver(usb_serial_tty_driver); put_tty_driver(usb_serial_tty_driver); bus_unregister(&usb_serial_bus_type); + idr_destroy(&serial_minors); } diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index caf188800c67..6b2479123de7 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -2065,6 +2065,18 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_READ_DISC_INFO ), +/* Reported by Oliver Neukum <oneukum@suse.com> + * This device morphes spontaneously into another device if the access + * pattern of Windows isn't followed. Thus writable media would be dirty + * if the initial instance is used. So the device is limited to its + * virtual CD. + * And yes, the concept that BCD goes up to 9 is not heeded */ +UNUSUAL_DEV( 0x19d2, 0x1225, 0x0000, 0xffff, + "ZTE,Incorporated", + "ZTE WCDMA Technologies MSM", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_SINGLE_LUN ), + /* Reported by Sven Geggus <sven-usbst@geggus.net> * This encrypted pen drive returns bogus data for the initial READ(10). */ @@ -2074,6 +2086,17 @@ UNUSUAL_DEV( 0x1b1c, 0x1ab5, 0x0200, 0x0200, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_INITIAL_READ10 ), +/* Reported by Hans de Goede <hdegoede@redhat.com> + * These are mini projectors using USB for both power and video data transport + * The usb-storage interface is a virtual windows driver CD, which the gm12u320 + * driver automatically converts into framebuffer & kms dri device nodes. + */ +UNUSUAL_DEV( 0x1de1, 0xc102, 0x0000, 0xffff, + "Grain-media Technology Corp.", + "USB3.0 Device GM12U320", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_IGNORE_DEVICE ), + /* Patch by Richard Schütz <r.schtz@t-online.de> * This external hard drive enclosure uses a JMicron chip which * needs the US_FL_IGNORE_RESIDUE flag to work properly. */ diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 2fb29dfeffbd..563c510f285c 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -689,6 +689,23 @@ struct vfio_device *vfio_device_get_from_dev(struct device *dev) } EXPORT_SYMBOL_GPL(vfio_device_get_from_dev); +static struct vfio_device *vfio_device_get_from_name(struct vfio_group *group, + char *buf) +{ + struct vfio_device *device; + + mutex_lock(&group->device_lock); + list_for_each_entry(device, &group->device_list, group_next) { + if (!strcmp(dev_name(device->dev), buf)) { + vfio_device_get(device); + break; + } + } + mutex_unlock(&group->device_lock); + + return device; +} + /* * Caller must hold a reference to the vfio_device */ @@ -1198,53 +1215,53 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf) { struct vfio_device *device; struct file *filep; - int ret = -ENODEV; + int ret; if (0 == atomic_read(&group->container_users) || !group->container->iommu_driver || !vfio_group_viable(group)) return -EINVAL; - mutex_lock(&group->device_lock); - list_for_each_entry(device, &group->device_list, group_next) { - if (strcmp(dev_name(device->dev), buf)) - continue; + device = vfio_device_get_from_name(group, buf); + if (!device) + return -ENODEV; - ret = device->ops->open(device->device_data); - if (ret) - break; - /* - * We can't use anon_inode_getfd() because we need to modify - * the f_mode flags directly to allow more than just ioctls - */ - ret = get_unused_fd_flags(O_CLOEXEC); - if (ret < 0) { - device->ops->release(device->device_data); - break; - } + ret = device->ops->open(device->device_data); + if (ret) { + vfio_device_put(device); + return ret; + } - filep = anon_inode_getfile("[vfio-device]", &vfio_device_fops, - device, O_RDWR); - if (IS_ERR(filep)) { - put_unused_fd(ret); - ret = PTR_ERR(filep); - device->ops->release(device->device_data); - break; - } + /* + * We can't use anon_inode_getfd() because we need to modify + * the f_mode flags directly to allow more than just ioctls + */ + ret = get_unused_fd_flags(O_CLOEXEC); + if (ret < 0) { + device->ops->release(device->device_data); + vfio_device_put(device); + return ret; + } - /* - * TODO: add an anon_inode interface to do this. - * Appears to be missing by lack of need rather than - * explicitly prevented. Now there's need. - */ - filep->f_mode |= (FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); + filep = anon_inode_getfile("[vfio-device]", &vfio_device_fops, + device, O_RDWR); + if (IS_ERR(filep)) { + put_unused_fd(ret); + ret = PTR_ERR(filep); + device->ops->release(device->device_data); + vfio_device_put(device); + return ret; + } + + /* + * TODO: add an anon_inode interface to do this. + * Appears to be missing by lack of need rather than + * explicitly prevented. Now there's need. + */ + filep->f_mode |= (FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); - vfio_device_get(device); - atomic_inc(&group->container_users); + atomic_inc(&group->container_users); - fd_install(ret, filep); - break; - } - mutex_unlock(&group->device_lock); + fd_install(ret, filep); return ret; } diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 9e8e004bb1c3..eec2f11809ff 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -22,14 +22,20 @@ #include <linux/file.h> #include <linux/highmem.h> #include <linux/slab.h> +#include <linux/vmalloc.h> #include <linux/kthread.h> #include <linux/cgroup.h> #include <linux/module.h> +#include <linux/sort.h> #include "vhost.h" +static ushort max_mem_regions = 64; +module_param(max_mem_regions, ushort, 0444); +MODULE_PARM_DESC(max_mem_regions, + "Maximum number of memory regions in memory map. (default: 64)"); + enum { - VHOST_MEMORY_MAX_NREGIONS = 64, VHOST_MEMORY_F_LOG = 0x1, }; @@ -543,7 +549,7 @@ void vhost_dev_cleanup(struct vhost_dev *dev, bool locked) fput(dev->log_file); dev->log_file = NULL; /* No one will access memory at this point */ - kfree(dev->memory); + kvfree(dev->memory); dev->memory = NULL; WARN_ON(!list_empty(&dev->work_list)); if (dev->worker) { @@ -663,6 +669,25 @@ int vhost_vq_access_ok(struct vhost_virtqueue *vq) } EXPORT_SYMBOL_GPL(vhost_vq_access_ok); +static int vhost_memory_reg_sort_cmp(const void *p1, const void *p2) +{ + const struct vhost_memory_region *r1 = p1, *r2 = p2; + if (r1->guest_phys_addr < r2->guest_phys_addr) + return 1; + if (r1->guest_phys_addr > r2->guest_phys_addr) + return -1; + return 0; +} + +static void *vhost_kvzalloc(unsigned long size) +{ + void *n = kzalloc(size, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT); + + if (!n) + n = vzalloc(size); + return n; +} + static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) { struct vhost_memory mem, *newmem, *oldmem; @@ -673,21 +698,23 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) return -EFAULT; if (mem.padding) return -EOPNOTSUPP; - if (mem.nregions > VHOST_MEMORY_MAX_NREGIONS) + if (mem.nregions > max_mem_regions) return -E2BIG; - newmem = kmalloc(size + mem.nregions * sizeof *m->regions, GFP_KERNEL); + newmem = vhost_kvzalloc(size + mem.nregions * sizeof(*m->regions)); if (!newmem) return -ENOMEM; memcpy(newmem, &mem, size); if (copy_from_user(newmem->regions, m->regions, mem.nregions * sizeof *m->regions)) { - kfree(newmem); + kvfree(newmem); return -EFAULT; } + sort(newmem->regions, newmem->nregions, sizeof(*newmem->regions), + vhost_memory_reg_sort_cmp, NULL); if (!memory_access_ok(d, newmem, 0)) { - kfree(newmem); + kvfree(newmem); return -EFAULT; } oldmem = d->memory; @@ -699,7 +726,7 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) d->vqs[i]->memory = newmem; mutex_unlock(&d->vqs[i]->mutex); } - kfree(oldmem); + kvfree(oldmem); return 0; } @@ -965,6 +992,7 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp) } if (eventfp != d->log_file) { filep = d->log_file; + d->log_file = eventfp; ctx = d->log_ctx; d->log_ctx = eventfp ? eventfd_ctx_fileget(eventfp) : NULL; @@ -992,17 +1020,22 @@ EXPORT_SYMBOL_GPL(vhost_dev_ioctl); static const struct vhost_memory_region *find_region(struct vhost_memory *mem, __u64 addr, __u32 len) { - struct vhost_memory_region *reg; - int i; + const struct vhost_memory_region *reg; + int start = 0, end = mem->nregions; - /* linear search is not brilliant, but we really have on the order of 6 - * regions in practice */ - for (i = 0; i < mem->nregions; ++i) { - reg = mem->regions + i; - if (reg->guest_phys_addr <= addr && - reg->guest_phys_addr + reg->memory_size - 1 >= addr) - return reg; + while (start < end) { + int slot = start + (end - start) / 2; + reg = mem->regions + slot; + if (addr >= reg->guest_phys_addr) + end = slot; + else + start = slot + 1; } + + reg = mem->regions + start; + if (addr >= reg->guest_phys_addr && + reg->guest_phys_addr + reg->memory_size > addr) + return reg; return NULL; } diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index 2d98de535e0f..230790984088 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -2475,3 +2475,17 @@ config FB_SSD1307 help This driver implements support for the Solomon SSD1307 OLED controller over I2C. + +config FB_SM712 + tristate "Silicon Motion SM712 framebuffer support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Frame buffer driver for the Silicon Motion SM710, SM712, SM721 + and SM722 chips. + + This driver is also available as a module. The module will be + called sm712fb. If you want to compile it as a module, say M + here and read <file:Documentation/kbuild/modules.txt>. diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile index cecea5063a80..50ed1b4fc2bf 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile @@ -131,6 +131,7 @@ obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o obj-$(CONFIG_FB_HYPERV) += hyperv_fb.o obj-$(CONFIG_FB_OPENCORES) += ocfb.o +obj-$(CONFIG_FB_SM712) += sm712fb.o # Platform or fallback drivers go here obj-$(CONFIG_FB_UVESA) += uvesafb.o diff --git a/drivers/staging/sm7xxfb/sm7xx.h b/drivers/video/fbdev/sm712.h index aad1cc4be34a..aad1cc4be34a 100644 --- a/drivers/staging/sm7xxfb/sm7xx.h +++ b/drivers/video/fbdev/sm712.h diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/video/fbdev/sm712fb.c index 07c2199c9ac7..629bfa2d2f51 100644 --- a/drivers/staging/sm7xxfb/sm7xxfb.c +++ b/drivers/video/fbdev/sm712fb.c @@ -32,7 +32,7 @@ #include <linux/pm.h> #endif -#include "sm7xx.h" +#include "sm712.h" /* * Private structure diff --git a/drivers/video/fbdev/stifb.c b/drivers/video/fbdev/stifb.c index 86621fabbb8b..735355b0e023 100644 --- a/drivers/video/fbdev/stifb.c +++ b/drivers/video/fbdev/stifb.c @@ -121,6 +121,7 @@ static int __initdata stifb_bpp_pref[MAX_STI_ROMS]; #define REG_3 0x0004a0 #define REG_4 0x000600 #define REG_6 0x000800 +#define REG_7 0x000804 #define REG_8 0x000820 #define REG_9 0x000a04 #define REG_10 0x018000 @@ -135,6 +136,8 @@ static int __initdata stifb_bpp_pref[MAX_STI_ROMS]; #define REG_21 0x200218 #define REG_22 0x0005a0 #define REG_23 0x0005c0 +#define REG_24 0x000808 +#define REG_25 0x000b00 #define REG_26 0x200118 #define REG_27 0x200308 #define REG_32 0x21003c @@ -429,6 +432,9 @@ ARTIST_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable) #define SET_LENXY_START_RECFILL(fb, lenxy) \ WRITE_WORD(lenxy, fb, REG_9) +#define SETUP_COPYAREA(fb) \ + WRITE_BYTE(0, fb, REG_16b1) + static void HYPER_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable) { @@ -1004,6 +1010,36 @@ stifb_blank(int blank_mode, struct fb_info *info) return 0; } +static void +stifb_copyarea(struct fb_info *info, const struct fb_copyarea *area) +{ + struct stifb_info *fb = container_of(info, struct stifb_info, info); + + SETUP_COPYAREA(fb); + + SETUP_HW(fb); + if (fb->info.var.bits_per_pixel == 32) { + WRITE_WORD(0xBBA0A000, fb, REG_10); + + NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xffffffff); + } else { + WRITE_WORD(fb->id == S9000_ID_HCRX ? 0x13a02000 : 0x13a01000, fb, REG_10); + + NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xff); + } + + NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb, + IBOvals(RopSrc, MaskAddrOffset(0), + BitmapExtent08, StaticReg(1), + DataDynamic, MaskOtc, BGx(0), FGx(0))); + + WRITE_WORD(((area->sx << 16) | area->sy), fb, REG_24); + WRITE_WORD(((area->width << 16) | area->height), fb, REG_7); + WRITE_WORD(((area->dx << 16) | area->dy), fb, REG_25); + + SETUP_FB(fb); +} + static void __init stifb_init_display(struct stifb_info *fb) { @@ -1069,7 +1105,7 @@ static struct fb_ops stifb_ops = { .fb_setcolreg = stifb_setcolreg, .fb_blank = stifb_blank, .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, + .fb_copyarea = stifb_copyarea, .fb_imageblit = cfb_imageblit, }; @@ -1258,7 +1294,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) info->fbops = &stifb_ops; info->screen_base = ioremap_nocache(REGION_BASE(fb,1), fix->smem_len); info->screen_size = fix->smem_len; - info->flags = FBINFO_DEFAULT; + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA; info->pseudo_palette = &fb->pseudo_palette; /* This has to be done !!! */ diff --git a/drivers/virtio/virtio_input.c b/drivers/virtio/virtio_input.c index 60e2a1677563..c96944b59856 100644 --- a/drivers/virtio/virtio_input.c +++ b/drivers/virtio/virtio_input.c @@ -313,6 +313,7 @@ err_init_vq: static void virtinput_remove(struct virtio_device *vdev) { struct virtio_input *vi = vdev->priv; + void *buf; unsigned long flags; spin_lock_irqsave(&vi->lock, flags); @@ -320,6 +321,9 @@ static void virtinput_remove(struct virtio_device *vdev) spin_unlock_irqrestore(&vi->lock, flags); input_unregister_device(vi->idev); + vdev->config->reset(vdev); + while ((buf = virtqueue_detach_unused_buf(vi->sts)) != NULL) + kfree(buf); vdev->config->del_vqs(vdev); kfree(vi); } diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index c1b03f4235b9..4e7fec36f5c3 100644 --- a/drivers/watchdog/sp805_wdt.c +++ b/drivers/watchdog/sp805_wdt.c @@ -4,7 +4,7 @@ * Watchdog driver for ARM SP805 watchdog module * * Copyright (C) 2010 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2 or later. This program is licensed "as is" without any @@ -303,6 +303,6 @@ static struct amba_driver sp805_wdt_driver = { module_amba_driver(sp805_wdt_driver); -MODULE_AUTHOR("Viresh Kumar <viresh.linux@gmail.com>"); +MODULE_AUTHOR("Viresh Kumar <vireshk@kernel.org>"); MODULE_DESCRIPTION("ARM SP805 Watchdog Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index fd933695f232..bf4a23c7c591 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -472,7 +472,7 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) } /* - * We avoid multiple worker processes conflicting via the balloon mutex. + * As this is a work item it is guaranteed to run as a single instance only. * We may of course race updates of the target counts (which are protected * by the balloon lock), or with changes to the Xen hard limit, but we will * recover from these in time. @@ -482,9 +482,10 @@ static void balloon_process(struct work_struct *work) enum bp_state state = BP_DONE; long credit; - mutex_lock(&balloon_mutex); do { + mutex_lock(&balloon_mutex); + credit = current_credit(); if (credit > 0) { @@ -499,17 +500,15 @@ static void balloon_process(struct work_struct *work) state = update_schedule(state); -#ifndef CONFIG_PREEMPT - if (need_resched()) - schedule(); -#endif + mutex_unlock(&balloon_mutex); + + cond_resched(); + } while (credit && state == BP_DONE); /* Schedule more work if there is some still to be done. */ if (state == BP_EAGAIN) schedule_delayed_work(&balloon_worker, balloon_stats.schedule_delay * HZ); - - mutex_unlock(&balloon_mutex); } /* Resets the Xen limit, sets new target, and kicks off processing. */ diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index 96093ae369a5..1495eccb1617 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c @@ -452,10 +452,12 @@ static void xen_free_irq(unsigned irq) irq_free_desc(irq); } -static void xen_evtchn_close(unsigned int port) +static void xen_evtchn_close(unsigned int port, unsigned int cpu) { struct evtchn_close close; + xen_evtchn_op_close(port, cpu); + close.port = port; if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0) BUG(); @@ -544,7 +546,7 @@ out: err: pr_err("irq%d: Failed to set port to irq mapping (%d)\n", irq, rc); - xen_evtchn_close(evtchn); + xen_evtchn_close(evtchn, NR_CPUS); return 0; } @@ -565,7 +567,7 @@ static void shutdown_pirq(struct irq_data *data) return; mask_evtchn(evtchn); - xen_evtchn_close(evtchn); + xen_evtchn_close(evtchn, cpu_from_evtchn(evtchn)); xen_irq_info_cleanup(info); } @@ -609,7 +611,7 @@ static void __unbind_from_irq(unsigned int irq) if (VALID_EVTCHN(evtchn)) { unsigned int cpu = cpu_from_irq(irq); - xen_evtchn_close(evtchn); + xen_evtchn_close(evtchn, cpu); switch (type_from_irq(irq)) { case IRQT_VIRQ: diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c index ed673e1acd61..6df8aac966b9 100644 --- a/drivers/xen/events/events_fifo.c +++ b/drivers/xen/events/events_fifo.c @@ -255,6 +255,12 @@ static void evtchn_fifo_unmask(unsigned port) } } +static bool evtchn_fifo_is_linked(unsigned port) +{ + event_word_t *word = event_word_from_port(port); + return sync_test_bit(EVTCHN_FIFO_BIT(LINKED, word), BM(word)); +} + static uint32_t clear_linked(volatile event_word_t *word) { event_word_t new, old, w; @@ -281,7 +287,8 @@ static void handle_irq_for_port(unsigned port) static void consume_one_event(unsigned cpu, struct evtchn_fifo_control_block *control_block, - unsigned priority, unsigned long *ready) + unsigned priority, unsigned long *ready, + bool drop) { struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu); uint32_t head; @@ -313,13 +320,15 @@ static void consume_one_event(unsigned cpu, if (head == 0) clear_bit(priority, ready); - if (evtchn_fifo_is_pending(port) && !evtchn_fifo_is_masked(port)) - handle_irq_for_port(port); + if (evtchn_fifo_is_pending(port) && !evtchn_fifo_is_masked(port)) { + if (likely(!drop)) + handle_irq_for_port(port); + } q->head[priority] = head; } -static void evtchn_fifo_handle_events(unsigned cpu) +static void __evtchn_fifo_handle_events(unsigned cpu, bool drop) { struct evtchn_fifo_control_block *control_block; unsigned long ready; @@ -331,11 +340,16 @@ static void evtchn_fifo_handle_events(unsigned cpu) while (ready) { q = find_first_bit(&ready, EVTCHN_FIFO_MAX_QUEUES); - consume_one_event(cpu, control_block, q, &ready); + consume_one_event(cpu, control_block, q, &ready, drop); ready |= xchg(&control_block->ready, 0); } } +static void evtchn_fifo_handle_events(unsigned cpu) +{ + __evtchn_fifo_handle_events(cpu, false); +} + static void evtchn_fifo_resume(void) { unsigned cpu; @@ -371,6 +385,26 @@ static void evtchn_fifo_resume(void) event_array_pages = 0; } +static void evtchn_fifo_close(unsigned port, unsigned int cpu) +{ + if (cpu == NR_CPUS) + return; + + get_online_cpus(); + if (cpu_online(cpu)) { + if (WARN_ON(irqs_disabled())) + goto out; + + while (evtchn_fifo_is_linked(port)) + cpu_relax(); + } else { + __evtchn_fifo_handle_events(cpu, true); + } + +out: + put_online_cpus(); +} + static const struct evtchn_ops evtchn_ops_fifo = { .max_channels = evtchn_fifo_max_channels, .nr_channels = evtchn_fifo_nr_channels, @@ -384,6 +418,7 @@ static const struct evtchn_ops evtchn_ops_fifo = { .unmask = evtchn_fifo_unmask, .handle_events = evtchn_fifo_handle_events, .resume = evtchn_fifo_resume, + .close = evtchn_fifo_close, }; static int evtchn_fifo_alloc_control_block(unsigned cpu) diff --git a/drivers/xen/events/events_internal.h b/drivers/xen/events/events_internal.h index 50c2050a1e32..d18e12315ec0 100644 --- a/drivers/xen/events/events_internal.h +++ b/drivers/xen/events/events_internal.h @@ -68,6 +68,7 @@ struct evtchn_ops { bool (*test_and_set_mask)(unsigned port); void (*mask)(unsigned port); void (*unmask)(unsigned port); + void (*close)(unsigned port, unsigned cpu); void (*handle_events)(unsigned cpu); void (*resume)(void); @@ -145,6 +146,12 @@ static inline void xen_evtchn_resume(void) evtchn_ops->resume(); } +static inline void xen_evtchn_op_close(unsigned port, unsigned cpu) +{ + if (evtchn_ops->close) + return evtchn_ops->close(port, cpu); +} + void xen_evtchn_2l_init(void); int xen_evtchn_fifo_init(void); diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 67b9163db718..0dbb222daaf1 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -568,12 +568,14 @@ static int gntdev_release(struct inode *inode, struct file *flip) pr_debug("priv %p\n", priv); + mutex_lock(&priv->lock); while (!list_empty(&priv->maps)) { map = list_entry(priv->maps.next, struct grant_map, next); list_del(&map->next); gntdev_put_map(NULL /* already removed */, map); } WARN_ON(!list_empty(&priv->freeable_maps)); + mutex_unlock(&priv->lock); if (use_ptemod) mmu_notifier_unregister(&priv->mn, priv->mm); |