diff options
Diffstat (limited to 'drivers')
172 files changed, 2085 insertions, 4464 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 973bf2ad4e0d..63c143e54a57 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -689,15 +689,19 @@ int bus_add_driver(struct device_driver *drv) printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n", __func__, drv->name); } - error = add_bind_files(drv); - if (error) { - /* Ditto */ - printk(KERN_ERR "%s: add_bind_files(%s) failed\n", - __func__, drv->name); + + if (!drv->suppress_bind_attrs) { + error = add_bind_files(drv); + if (error) { + /* Ditto */ + printk(KERN_ERR "%s: add_bind_files(%s) failed\n", + __func__, drv->name); + } } kobject_uevent(&priv->kobj, KOBJ_ADD); return 0; + out_unregister: kfree(drv->p); drv->p = NULL; @@ -720,7 +724,8 @@ void bus_remove_driver(struct device_driver *drv) if (!drv->bus) return; - remove_bind_files(drv); + if (!drv->suppress_bind_attrs) + remove_bind_files(drv); driver_remove_attrs(drv->bus, drv); driver_remove_file(drv, &driver_attr_uevent); klist_remove(&drv->p->knode_bus); diff --git a/drivers/base/driver.c b/drivers/base/driver.c index ed2ebd3c287d..f367885a7646 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -236,7 +236,7 @@ int driver_register(struct device_driver *drv) put_driver(other); printk(KERN_ERR "Error: Driver '%s' is already registered, " "aborting...\n", drv->name); - return -EEXIST; + return -EBUSY; } ret = bus_add_driver(drv); diff --git a/drivers/base/platform.c b/drivers/base/platform.c index ed156a13aa40..4fa954b07ac4 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -521,11 +521,15 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv, { int retval, code; + /* make sure driver won't have bind/unbind attributes */ + drv->driver.suppress_bind_attrs = true; + /* temporary section violation during probe() */ drv->probe = probe; retval = code = platform_driver_register(drv); - /* Fixup that section violation, being paranoid about code scanning + /* + * Fixup that section violation, being paranoid about code scanning * the list of drivers in order to probe new devices. Check to see * if the probe was successful, and make sure any forced probes of * new devices fail. diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index e0dc4071e088..8aa2443182d5 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -511,6 +511,7 @@ static void dpm_complete(pm_message_t state) INIT_LIST_HEAD(&list); mutex_lock(&dpm_list_mtx); + transition_started = false; while (!list_empty(&dpm_list)) { struct device *dev = to_device(dpm_list.prev); diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 38556f6cc22d..a770498a74ec 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -51,8 +51,6 @@ static int __pm_runtime_idle(struct device *dev) { int retval = 0; - dev_dbg(dev, "__pm_runtime_idle()!\n"); - if (dev->power.runtime_error) retval = -EINVAL; else if (dev->power.idle_notification) @@ -93,8 +91,6 @@ static int __pm_runtime_idle(struct device *dev) wake_up_all(&dev->power.wait_queue); out: - dev_dbg(dev, "__pm_runtime_idle() returns %d!\n", retval); - return retval; } diff --git a/drivers/block/loop.c b/drivers/block/loop.c index edda9ea7c626..bd112c8c7bcd 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -949,7 +949,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) lo->lo_state = Lo_unbound; /* This is safe: open() is still holding a reference. */ module_put(THIS_MODULE); - if (max_part > 0) + if (max_part > 0 && bdev) ioctl_by_bdev(bdev, BLKRRPART, 0); mutex_unlock(&lo->lo_ctl_mutex); /* diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 08a6f50ae791..6aad99ec4e0f 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -323,7 +323,7 @@ config SPECIALIX config SX tristate "Specialix SX (and SI) card support" - depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) + depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) && BROKEN help This is a driver for the SX and SI multiport serial cards. Please read the file <file:Documentation/serial/sx.txt> for details. @@ -334,7 +334,7 @@ config SX config RIO tristate "Specialix RIO system support" - depends on SERIAL_NONSTANDARD + depends on SERIAL_NONSTANDARD && BROKEN help This is a driver for the Specialix RIO, a smart serial card which drives an outboard box that can support up to 128 ports. Product @@ -395,7 +395,7 @@ config NOZOMI config A2232 tristate "Commodore A2232 serial support (EXPERIMENTAL)" - depends on EXPERIMENTAL && ZORRO && BROKEN_ON_SMP + depends on EXPERIMENTAL && ZORRO && BROKEN ---help--- This option supports the 2232 7-port serial card shipped with the Amiga 2000 and other Zorro-bus machines, dating from 1989. At diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index ad41f19b8e3f..12fdd3987a36 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -76,8 +76,11 @@ static void cpuidle_idle_call(void) #endif /* ask the governor for the next state */ next_state = cpuidle_curr_governor->select(dev); - if (need_resched()) + if (need_resched()) { + local_irq_enable(); return; + } + target_state = &dev->states[next_state]; /* enter the state and update stats */ diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index d335086f4a26..77a9579d7167 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -1173,7 +1173,7 @@ static void i5000_get_mc_regs(struct mem_ctl_info *mci) pci_read_config_word(pvt->branch_1, where, &pvt->b1_mtr[slot_row]); debugf2("MTR%d where=0x%x B1 value=0x%x\n", slot_row, - where, pvt->b0_mtr[slot_row]); + where, pvt->b1_mtr[slot_row]); } else { pvt->b1_mtr[slot_row] = 0; } @@ -1232,7 +1232,7 @@ static int i5000_init_csrows(struct mem_ctl_info *mci) struct csrow_info *p_csrow; int empty, channel_count; int max_csrows; - int mtr; + int mtr, mtr1; int csrow_megs; int channel; int csrow; @@ -1251,9 +1251,10 @@ static int i5000_init_csrows(struct mem_ctl_info *mci) /* use branch 0 for the basis */ mtr = pvt->b0_mtr[csrow >> 1]; + mtr1 = pvt->b1_mtr[csrow >> 1]; /* if no DIMMS on this row, continue */ - if (!MTR_DIMMS_PRESENT(mtr)) + if (!MTR_DIMMS_PRESENT(mtr) && !MTR_DIMMS_PRESENT(mtr1)) continue; /* FAKE OUT VALUES, FIXME */ diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index b08b6d8e2dc7..f99d10655ed4 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c @@ -46,9 +46,10 @@ /* Limits for i5400 */ #define NUM_MTRS_PER_BRANCH 4 #define CHANNELS_PER_BRANCH 2 +#define MAX_DIMMS_PER_CHANNEL NUM_MTRS_PER_BRANCH #define MAX_CHANNELS 4 -#define MAX_DIMMS (MAX_CHANNELS * 4) /* Up to 4 DIMM's per channel */ -#define MAX_CSROWS (MAX_DIMMS * 2) /* max possible csrows per channel */ +/* max possible csrows per channel */ +#define MAX_CSROWS (MAX_DIMMS_PER_CHANNEL) /* Device 16, * Function 0: System Address @@ -331,7 +332,6 @@ static const struct i5400_dev_info i5400_devs[] = { struct i5400_dimm_info { int megabytes; /* size, 0 means not present */ - int dual_rank; }; /* driver private data structure */ @@ -849,11 +849,9 @@ static int determine_mtr(struct i5400_pvt *pvt, int csrow, int channel) int n; /* There is one MTR for each slot pair of FB-DIMMs, - Each slot may have one or two ranks (2 csrows), Each slot pair may be at branch 0 or branch 1. - So, csrow should be divided by eight */ - n = csrow >> 3; + n = csrow; if (n >= NUM_MTRS_PER_BRANCH) { debugf0("ERROR: trying to access an invalid csrow: %d\n", @@ -905,25 +903,22 @@ static void handle_channel(struct i5400_pvt *pvt, int csrow, int channel, amb_present_reg = determine_amb_present_reg(pvt, channel); /* Determine if there is a DIMM present in this DIMM slot */ - if (amb_present_reg & (1 << (csrow >> 1))) { - dinfo->dual_rank = MTR_DIMM_RANK(mtr); - - if (!((dinfo->dual_rank == 0) && - ((csrow & 0x1) == 0x1))) { - /* Start with the number of bits for a Bank - * on the DRAM */ - addrBits = MTR_DRAM_BANKS_ADDR_BITS(mtr); - /* Add thenumber of ROW bits */ - addrBits += MTR_DIMM_ROWS_ADDR_BITS(mtr); - /* add the number of COLUMN bits */ - addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr); - - addrBits += 6; /* add 64 bits per DIMM */ - addrBits -= 20; /* divide by 2^^20 */ - addrBits -= 3; /* 8 bits per bytes */ - - dinfo->megabytes = 1 << addrBits; - } + if (amb_present_reg & (1 << csrow)) { + /* Start with the number of bits for a Bank + * on the DRAM */ + addrBits = MTR_DRAM_BANKS_ADDR_BITS(mtr); + /* Add thenumber of ROW bits */ + addrBits += MTR_DIMM_ROWS_ADDR_BITS(mtr); + /* add the number of COLUMN bits */ + addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr); + /* add the number of RANK bits */ + addrBits += MTR_DIMM_RANK(mtr); + + addrBits += 6; /* add 64 bits per DIMM */ + addrBits -= 20; /* divide by 2^^20 */ + addrBits -= 3; /* 8 bits per bytes */ + + dinfo->megabytes = 1 << addrBits; } } } @@ -951,12 +946,12 @@ static void calculate_dimm_size(struct i5400_pvt *pvt) return; } - /* Scan all the actual CSROWS (which is # of DIMMS * 2) + /* Scan all the actual CSROWS * and calculate the information for each DIMM * Start with the highest csrow first, to display it first * and work toward the 0th csrow */ - max_csrows = pvt->maxdimmperch * 2; + max_csrows = pvt->maxdimmperch; for (csrow = max_csrows - 1; csrow >= 0; csrow--) { /* on an odd csrow, first output a 'boundary' marker, @@ -1064,7 +1059,7 @@ static void i5400_get_mc_regs(struct mem_ctl_info *mci) /* Get the set of MTR[0-3] regs by each branch */ for (slot_row = 0; slot_row < NUM_MTRS_PER_BRANCH; slot_row++) { - int where = MTR0 + (slot_row * sizeof(u32)); + int where = MTR0 + (slot_row * sizeof(u16)); /* Branch 0 set of MTR registers */ pci_read_config_word(pvt->branch_0, where, @@ -1146,7 +1141,7 @@ static int i5400_init_csrows(struct mem_ctl_info *mci) pvt = mci->pvt_info; channel_count = pvt->maxch; - max_csrows = pvt->maxdimmperch * 2; + max_csrows = pvt->maxdimmperch; empty = 1; /* Assume NO memory */ @@ -1215,28 +1210,6 @@ static void i5400_enable_error_reporting(struct mem_ctl_info *mci) } /* - * i5400_get_dimm_and_channel_counts(pdev, &num_csrows, &num_channels) - * - * ask the device how many channels are present and how many CSROWS - * as well - */ -static void i5400_get_dimm_and_channel_counts(struct pci_dev *pdev, - int *num_dimms_per_channel, - int *num_channels) -{ - u8 value; - - /* Need to retrieve just how many channels and dimms per channel are - * supported on this memory controller - */ - pci_read_config_byte(pdev, MAXDIMMPERCH, &value); - *num_dimms_per_channel = (int)value * 2; - - pci_read_config_byte(pdev, MAXCH, &value); - *num_channels = (int)value; -} - -/* * i5400_probe1 Probe for ONE instance of device to see if it is * present. * return: @@ -1263,22 +1236,16 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx) if (PCI_FUNC(pdev->devfn) != 0) return -ENODEV; - /* Ask the devices for the number of CSROWS and CHANNELS so - * that we can calculate the memory resources, etc - * - * The Chipset will report what it can handle which will be greater - * or equal to what the motherboard manufacturer will implement. - * - * As we don't have a motherboard identification routine to determine + /* As we don't have a motherboard identification routine to determine * actual number of slots/dimms per channel, we thus utilize the * resource as specified by the chipset. Thus, we might have * have more DIMMs per channel than actually on the mobo, but this * allows the driver to support upto the chipset max, without * some fancy mobo determination. */ - i5400_get_dimm_and_channel_counts(pdev, &num_dimms_per_channel, - &num_channels); - num_csrows = num_dimms_per_channel * 2; + num_dimms_per_channel = MAX_DIMMS_PER_CHANNEL; + num_channels = MAX_CHANNELS; + num_csrows = num_dimms_per_channel; debugf0("MC: %s(): Number of - Channels= %d DIMMS= %d CSROWS= %d\n", __func__, num_channels, num_dimms_per_channel, num_csrows); diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 157f6504f25e..cf27402af97b 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -26,7 +26,9 @@ #include "mpc85xx_edac.h" static int edac_dev_idx; +#ifdef CONFIG_PCI static int edac_pci_idx; +#endif static int edac_mc_idx; static u32 orig_ddr_err_disable; diff --git a/drivers/gpio/twl4030-gpio.c b/drivers/gpio/twl4030-gpio.c index afad14792141..49384a7c5492 100644 --- a/drivers/gpio/twl4030-gpio.c +++ b/drivers/gpio/twl4030-gpio.c @@ -460,7 +460,8 @@ no_irqs: return ret; } -static int __devexit gpio_twl4030_remove(struct platform_device *pdev) +/* Cannot use __devexit as gpio_twl4030_probe() calls us */ +static int gpio_twl4030_remove(struct platform_device *pdev) { struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data; int status; @@ -493,7 +494,7 @@ static struct platform_driver gpio_twl4030_driver = { .driver.name = "twl4030_gpio", .driver.owner = THIS_MODULE, .probe = gpio_twl4030_probe, - .remove = __devexit_p(gpio_twl4030_remove), + .remove = gpio_twl4030_remove, }; static int __init gpio_twl4030_init(void) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 3c0d2b3aed76..cea665d86dd3 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -626,6 +626,12 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, return NULL; } + /* it is incorrect if hsync/vsync width is zero */ + if (!hsync_pulse_width || !vsync_pulse_width) { + DRM_DEBUG_KMS("Incorrect Detailed timing. " + "Wrong Hsync/Vsync pulse width\n"); + return NULL; + } mode = drm_mode_create(dev); if (!mode) return NULL; @@ -647,6 +653,15 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, mode->vsync_end = mode->vsync_start + vsync_pulse_width; mode->vtotal = mode->vdisplay + vblank; + /* perform the basic check for the detailed timing */ + if (mode->hsync_end > mode->htotal || + mode->vsync_end > mode->vtotal) { + drm_mode_destroy(dev, mode); + DRM_DEBUG_KMS("Incorrect detailed timing. " + "Sync is beyond the blank.\n"); + return NULL; + } + drm_mode_set_name(mode); if (pt->misc & DRM_EDID_PT_INTERLACED) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 23dc9c115fd9..9c924614c418 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -454,22 +454,39 @@ out_free: } EXPORT_SYMBOL(drm_fb_helper_init_crtc_count); -static void setcolreg(struct drm_crtc *crtc, u16 red, u16 green, +static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, u16 regno, struct fb_info *info) { struct drm_fb_helper *fb_helper = info->par; struct drm_framebuffer *fb = fb_helper->fb; int pindex; + if (info->fix.visual == FB_VISUAL_TRUECOLOR) { + u32 *palette; + u32 value; + /* place color in psuedopalette */ + if (regno > 16) + return -EINVAL; + palette = (u32 *)info->pseudo_palette; + red >>= (16 - info->var.red.length); + green >>= (16 - info->var.green.length); + blue >>= (16 - info->var.blue.length); + value = (red << info->var.red.offset) | + (green << info->var.green.offset) | + (blue << info->var.blue.offset); + palette[regno] = value; + return 0; + } + pindex = regno; if (fb->bits_per_pixel == 16) { pindex = regno << 3; if (fb->depth == 16 && regno > 63) - return; + return -EINVAL; if (fb->depth == 15 && regno > 31) - return; + return -EINVAL; if (fb->depth == 16) { u16 r, g, b; @@ -493,13 +510,7 @@ static void setcolreg(struct drm_crtc *crtc, u16 red, u16 green, if (fb->depth != 16) fb_helper->funcs->gamma_set(crtc, red, green, blue, pindex); - - if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) { - ((u32 *) fb->pseudo_palette)[regno] = - (regno << info->var.red.offset) | - (regno << info->var.green.offset) | - (regno << info->var.blue.offset); - } + return 0; } int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) @@ -536,7 +547,9 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) if (transp) htransp = *transp++; - setcolreg(crtc, hred, hgreen, hblue, start++, info); + rc = setcolreg(crtc, hred, hgreen, hblue, start++, info); + if (rc) + return rc; } crtc_funcs->load_lut(crtc); } @@ -555,6 +568,7 @@ int drm_fb_helper_setcolreg(unsigned regno, struct drm_device *dev = fb_helper->dev; struct drm_crtc *crtc; int i; + int ret; if (regno > 255) return 1; @@ -568,8 +582,10 @@ int drm_fb_helper_setcolreg(unsigned regno, if (i == fb_helper->crtc_count) continue; + ret = setcolreg(crtc, red, green, blue, regno, info); + if (ret) + return ret; - setcolreg(crtc, red, green, blue, regno, info); crtc_funcs->load_lut(crtc); } return 0; @@ -928,7 +944,7 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, { info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR : - FB_VISUAL_DIRECTCOLOR; + FB_VISUAL_TRUECOLOR; info->fix.type_aux = 0; info->fix.xpanstep = 1; /* doing it in hw */ info->fix.ypanstep = 1; /* doing it in hw */ diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index b93814c0d3e2..7f436ec075f6 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -89,7 +89,8 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) pci_set_power_state(dev->pdev, PCI_D3hot); } - dev_priv->suspended = 1; + /* Modeset on resume, not lid events */ + dev_priv->modeset_on_lid = 0; return 0; } @@ -124,7 +125,7 @@ static int i915_resume(struct drm_device *dev) drm_helper_resume_force_mode(dev); } - dev_priv->suspended = 0; + dev_priv->modeset_on_lid = 0; return ret; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6035d3dae851..c5df2234418d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -274,7 +274,7 @@ typedef struct drm_i915_private { struct drm_i915_display_funcs display; /* Register state */ - bool suspended; + bool modeset_on_lid; u8 saveLBB; u32 saveDSPACNTR; u32 saveDSPBCNTR; diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 98ae3d73577e..808bbe412ba8 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -656,6 +656,15 @@ static int intel_lvds_get_modes(struct drm_connector *connector) return 0; } +/* + * Lid events. Note the use of 'modeset_on_lid': + * - we set it on lid close, and reset it on open + * - we use it as a "only once" bit (ie we ignore + * duplicate events where it was already properly + * set/reset) + * - the suspend/resume paths will also set it to + * zero, since they restore the mode ("lid open"). + */ static int intel_lid_notify(struct notifier_block *nb, unsigned long val, void *unused) { @@ -663,13 +672,19 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val, container_of(nb, struct drm_i915_private, lid_notifier); struct drm_device *dev = dev_priv->dev; - if (acpi_lid_open() && !dev_priv->suspended) { - mutex_lock(&dev->mode_config.mutex); - drm_helper_resume_force_mode(dev); - mutex_unlock(&dev->mode_config.mutex); + if (!acpi_lid_open()) { + dev_priv->modeset_on_lid = 1; + return NOTIFY_OK; } - drm_sysfs_hotplug_event(dev_priv->dev); + if (!dev_priv->modeset_on_lid) + return NOTIFY_OK; + + dev_priv->modeset_on_lid = 0; + + mutex_lock(&dev->mode_config.mutex); + drm_helper_resume_force_mode(dev); + mutex_unlock(&dev->mode_config.mutex); return NOTIFY_OK; } diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 3d667031de6e..df988142e6b0 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -582,10 +582,9 @@ int radeon_device_init(struct radeon_device *rdev, DRM_INFO("register mmio size: %u\n", (unsigned)rdev->rmmio_size); /* if we have > 1 VGA cards, then disable the radeon VGA resources */ - r = vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode); - if (r) { - return -EINVAL; - } + /* this will fail for cards that aren't VGA class devices, just + * ignore it */ + vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode); r = radeon_init(rdev); if (r) diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index 2c2cb1ec94c5..27d62574284f 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c @@ -572,7 +572,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) /* Sample register contents every 1 sec */ if (time_after(jiffies, data->last_update + HZ) || !data->valid) { - if (data->type != sch5027) { + if (data->type == dme1737) { data->vid = dme1737_read(data, DME1737_REG_VID) & 0x3f; } @@ -1621,9 +1621,6 @@ static struct attribute *dme1737_misc_attr[] = { &sensor_dev_attr_zone1_auto_point1_temp_hyst.dev_attr.attr, &sensor_dev_attr_zone2_auto_point1_temp_hyst.dev_attr.attr, &sensor_dev_attr_zone3_auto_point1_temp_hyst.dev_attr.attr, - /* Misc */ - &dev_attr_vrm.attr, - &dev_attr_cpu0_vid.attr, NULL }; @@ -1631,6 +1628,18 @@ static const struct attribute_group dme1737_misc_group = { .attrs = dme1737_misc_attr, }; +/* The following struct holds VID-related attributes. Their creation + depends on the chip type which is determined during module load. */ +static struct attribute *dme1737_vid_attr[] = { + &dev_attr_vrm.attr, + &dev_attr_cpu0_vid.attr, + NULL +}; + +static const struct attribute_group dme1737_vid_group = { + .attrs = dme1737_vid_attr, +}; + /* The following structs hold the PWM attributes, some of which are optional. * Their creation depends on the chip configuration which is determined during * module load. */ @@ -1902,6 +1911,9 @@ static void dme1737_remove_files(struct device *dev) if (data->type != sch5027) { sysfs_remove_group(&dev->kobj, &dme1737_misc_group); } + if (data->type == dme1737) { + sysfs_remove_group(&dev->kobj, &dme1737_vid_group); + } sysfs_remove_group(&dev->kobj, &dme1737_group); @@ -1933,6 +1945,13 @@ static int dme1737_create_files(struct device *dev) goto exit_remove; } + /* Create VID-related sysfs attributes */ + if ((data->type == dme1737) && + (err = sysfs_create_group(&dev->kobj, + &dme1737_vid_group))) { + goto exit_remove; + } + /* Create fan sysfs attributes */ for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) { if (data->has_fan & (1 << ix)) { @@ -2127,7 +2146,7 @@ static int dme1737_init_device(struct device *dev) data->pwm_acz[2] = 4; /* pwm3 -> zone3 */ /* Set VRM */ - if (data->type != sch5027) { + if (data->type == dme1737) { data->vrm = vid_which_vrm(); } diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c index 2a7a85a6dc36..da1b1f9488af 100644 --- a/drivers/hwmon/fschmd.c +++ b/drivers/hwmon/fschmd.c @@ -819,7 +819,7 @@ static int watchdog_release(struct inode *inode, struct file *filp) static ssize_t watchdog_write(struct file *filp, const char __user *buf, size_t count, loff_t *offset) { - size_t ret; + int ret; struct fschmd_data *data = filp->private_data; if (count) { diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c index 6679854c85b0..be475e844c2a 100644 --- a/drivers/hwmon/hp_accel.c +++ b/drivers/hwmon/hp_accel.c @@ -197,11 +197,13 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = { AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left), AXIS_DMI_MATCH("HP2140", "HP 2140", xy_swap_inverted), AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd), - AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd), + AXIS_DMI_MATCH("NC6730b", "HP Compaq 6730b", xy_rotated_left_usd), + AXIS_DMI_MATCH("NC6730s", "HP Compaq 6730s", xy_swap), AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right), AXIS_DMI_MATCH("NC6710x", "HP Compaq 6710", xy_swap_yz_inverted), AXIS_DMI_MATCH("NC6715x", "HP Compaq 6715", y_inverted), AXIS_DMI_MATCH("NC693xx", "HP EliteBook 693", xy_rotated_right), + AXIS_DMI_MATCH("NC693xx", "HP EliteBook 853", xy_swap), /* Intel-based HP Pavilion dv5 */ AXIS_DMI_MATCH2("HPDV5_I", PRODUCT_NAME, "HP Pavilion dv5", @@ -214,6 +216,7 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = { y_inverted), AXIS_DMI_MATCH("DV7", "HP Pavilion dv7", x_inverted), AXIS_DMI_MATCH("HP8710", "HP Compaq 8710", y_inverted), + AXIS_DMI_MATCH("HDX18", "HP HDX 18", x_inverted), { NULL, } /* Laptop models without axis info (yet): * "NC6910" "HP Compaq 6910" diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index ffeb2a10e1a7..a3749cb0f181 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -1028,12 +1028,11 @@ static int __init it87_find(unsigned short *address, chip_type, *address, sio_data->revision); /* Read GPIO config and VID value from LDN 7 (GPIO) */ - if (chip_type != IT8705F_DEVID) { + if (sio_data->type != it87) { int reg; superio_select(GPIO); - if ((chip_type == it8718) || - (chip_type == it8720)) + if (sio_data->type == it8718 || sio_data->type == it8720) sio_data->vid_value = superio_inb(IT87_SIO_VID_REG); reg = superio_inb(IT87_SIO_PINX2_REG); diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 4afba3ec2a61..e3654d683e15 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -120,19 +120,26 @@ struct imx_i2c_struct { wait_queue_head_t queue; unsigned long i2csr; unsigned int disable_delay; + int stopped; + unsigned int ifdr; /* IMX_I2C_IFDR */ }; /** Functions for IMX I2C adapter driver *************************************** *******************************************************************************/ -static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx) +static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy) { unsigned long orig_jiffies = jiffies; + unsigned int temp; dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); - /* wait for bus not busy */ - while (readb(i2c_imx->base + IMX_I2C_I2SR) & I2SR_IBB) { + while (1) { + temp = readb(i2c_imx->base + IMX_I2C_I2SR); + if (for_busy && (temp & I2SR_IBB)) + break; + if (!for_busy && !(temp & I2SR_IBB)) + break; if (signal_pending(current)) { dev_dbg(&i2c_imx->adapter.dev, "<%s> I2C Interrupted\n", __func__); @@ -179,41 +186,62 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx) return 0; } -static void i2c_imx_start(struct imx_i2c_struct *i2c_imx) +static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) { unsigned int temp = 0; + int result; dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); + clk_enable(i2c_imx->clk); + writeb(i2c_imx->ifdr, i2c_imx->base + IMX_I2C_IFDR); /* Enable I2C controller */ + writeb(0, i2c_imx->base + IMX_I2C_I2SR); writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR); + + /* Wait controller to be stable */ + udelay(50); + /* Start I2C transaction */ temp = readb(i2c_imx->base + IMX_I2C_I2CR); temp |= I2CR_MSTA; writeb(temp, i2c_imx->base + IMX_I2C_I2CR); + result = i2c_imx_bus_busy(i2c_imx, 1); + if (result) + return result; + i2c_imx->stopped = 0; + temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK; writeb(temp, i2c_imx->base + IMX_I2C_I2CR); + return result; } static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) { unsigned int temp = 0; - /* Stop I2C transaction */ - dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); - temp = readb(i2c_imx->base + IMX_I2C_I2CR); - temp &= ~I2CR_MSTA; - writeb(temp, i2c_imx->base + IMX_I2C_I2CR); - /* setup chip registers to defaults */ - writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR); - writeb(0, i2c_imx->base + IMX_I2C_I2SR); - /* - * This delay caused by an i.MXL hardware bug. - * If no (or too short) delay, no "STOP" bit will be generated. - */ - udelay(i2c_imx->disable_delay); + if (!i2c_imx->stopped) { + /* Stop I2C transaction */ + dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); + temp = readb(i2c_imx->base + IMX_I2C_I2CR); + temp &= ~(I2CR_MSTA | I2CR_MTX); + writeb(temp, i2c_imx->base + IMX_I2C_I2CR); + i2c_imx->stopped = 1; + } + if (cpu_is_mx1()) { + /* + * This delay caused by an i.MXL hardware bug. + * If no (or too short) delay, no "STOP" bit will be generated. + */ + udelay(i2c_imx->disable_delay); + } + + if (!i2c_imx->stopped) + i2c_imx_bus_busy(i2c_imx, 0); + /* Disable I2C controller */ writeb(0, i2c_imx->base + IMX_I2C_I2CR); + clk_disable(i2c_imx->clk); } static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, @@ -233,8 +261,8 @@ static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, else for (i = 0; i2c_clk_div[i][0] < div; i++); - /* Write divider value to register */ - writeb(i2c_clk_div[i][1], i2c_imx->base + IMX_I2C_IFDR); + /* Store divider value */ + i2c_imx->ifdr = i2c_clk_div[i][1]; /* * There dummy delay is calculated. @@ -341,11 +369,15 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) if (result) return result; if (i == (msgs->len - 1)) { + /* It must generate STOP before read I2DR to prevent + controller from generating another clock cycle */ dev_dbg(&i2c_imx->adapter.dev, "<%s> clear MSTA\n", __func__); temp = readb(i2c_imx->base + IMX_I2C_I2CR); - temp &= ~I2CR_MSTA; + temp &= ~(I2CR_MSTA | I2CR_MTX); writeb(temp, i2c_imx->base + IMX_I2C_I2CR); + i2c_imx_bus_busy(i2c_imx, 0); + i2c_imx->stopped = 1; } else if (i == (msgs->len - 2)) { dev_dbg(&i2c_imx->adapter.dev, "<%s> set TXAK\n", __func__); @@ -370,14 +402,11 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); - /* Check if i2c bus is not busy */ - result = i2c_imx_bus_busy(i2c_imx); + /* Start I2C transfer */ + result = i2c_imx_start(i2c_imx); if (result) goto fail0; - /* Start I2C transfer */ - i2c_imx_start(i2c_imx); - /* read/write data */ for (i = 0; i < num; i++) { if (i) { @@ -386,6 +415,9 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, temp = readb(i2c_imx->base + IMX_I2C_I2CR); temp |= I2CR_RSTA; writeb(temp, i2c_imx->base + IMX_I2C_I2CR); + result = i2c_imx_bus_busy(i2c_imx, 1); + if (result) + goto fail0; } dev_dbg(&i2c_imx->adapter.dev, "<%s> transfer message: %d\n", __func__, i); @@ -500,7 +532,6 @@ static int __init i2c_imx_probe(struct platform_device *pdev) dev_err(&pdev->dev, "can't get I2C clock\n"); goto fail3; } - clk_enable(i2c_imx->clk); /* Request IRQ */ ret = request_irq(i2c_imx->irq, i2c_imx_isr, 0, pdev->name, i2c_imx); @@ -549,7 +580,6 @@ static int __init i2c_imx_probe(struct platform_device *pdev) fail5: free_irq(i2c_imx->irq, i2c_imx); fail4: - clk_disable(i2c_imx->clk); clk_put(i2c_imx->clk); fail3: release_mem_region(i2c_imx->res->start, resource_size(res)); @@ -586,8 +616,6 @@ static int __exit i2c_imx_remove(struct platform_device *pdev) if (pdata && pdata->exit) pdata->exit(&pdev->dev); - /* Disable I2C clock */ - clk_disable(i2c_imx->clk); clk_put(i2c_imx->clk); release_mem_region(i2c_imx->res->start, resource_size(i2c_imx->res)); diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index d325e86e3103..f627001108b8 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -365,9 +365,6 @@ static int mpc_write(struct mpc_i2c *i2c, int target, unsigned timeout = i2c->adap.timeout; u32 flags = restart ? CCR_RSTA : 0; - /* Start with MEN */ - if (!restart) - writeccr(i2c, CCR_MEN); /* Start as master */ writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags); /* Write target byte */ @@ -396,9 +393,6 @@ static int mpc_read(struct mpc_i2c *i2c, int target, int i, result; u32 flags = restart ? CCR_RSTA : 0; - /* Start with MEN */ - if (!restart) - writeccr(i2c, CCR_MEN); /* Switch to read - restart */ writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags); /* Write target address byte - this time with the read flag set */ @@ -425,9 +419,9 @@ static int mpc_read(struct mpc_i2c *i2c, int target, /* Generate txack on next to last byte */ if (i == length - 2) writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK); - /* Generate stop on last byte */ + /* Do not generate stop on last byte */ if (i == length - 1) - writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_TXAK); + writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX); data[i] = readb(i2c->base + MPC_I2C_DR); } diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c index 680e5975217f..ca0c46f6580a 100644 --- a/drivers/ide/cmd64x.c +++ b/drivers/ide/cmd64x.c @@ -379,7 +379,8 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = { .enablebits = {{0x00,0x00,0x00}, {0x51,0x08,0x08}}, .port_ops = &cmd64x_port_ops, .host_flags = IDE_HFLAG_CLEAR_SIMPLEX | - IDE_HFLAG_ABUSE_PREFETCH, + IDE_HFLAG_ABUSE_PREFETCH | + IDE_HFLAG_SERIALIZE, .pio_mask = ATA_PIO5, .mwdma_mask = ATA_MWDMA2, .udma_mask = 0x00, /* no udma */ @@ -389,7 +390,8 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = { .init_chipset = init_chipset_cmd64x, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, .port_ops = &cmd648_port_ops, - .host_flags = IDE_HFLAG_ABUSE_PREFETCH, + .host_flags = IDE_HFLAG_ABUSE_PREFETCH | + IDE_HFLAG_SERIALIZE, .pio_mask = ATA_PIO5, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA2, diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index a6512372c7a3..4452eabbee6d 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -233,6 +233,7 @@ struct atkbd { */ static void (*atkbd_platform_fixup)(struct atkbd *, const void *data); static void *atkbd_platform_fixup_data; +static unsigned int (*atkbd_platform_scancode_fixup)(struct atkbd *, unsigned int); static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, ssize_t (*handler)(struct atkbd *, char *)); @@ -393,6 +394,9 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, input_event(dev, EV_MSC, MSC_RAW, code); + if (atkbd_platform_scancode_fixup) + code = atkbd_platform_scancode_fixup(atkbd, code); + if (atkbd->translated) { if (atkbd->emul || atkbd_need_xlate(atkbd->xl_bit, code)) { @@ -923,6 +927,22 @@ static unsigned int atkbd_volume_forced_release_keys[] = { }; /* + * OQO 01+ multimedia keys (64--66) generate e0 6x upon release whereas + * they should be generating e4-e6 (0x80 | code). + */ +static unsigned int atkbd_oqo_01plus_scancode_fixup(struct atkbd *atkbd, + unsigned int code) +{ + if (atkbd->translated && atkbd->emul == 1 && + (code == 0x64 || code == 0x65 || code == 0x66)) { + atkbd->emul = 0; + code |= 0x80; + } + + return code; +} + +/* * atkbd_set_keycode_table() initializes keyboard's keycode table * according to the selected scancode set */ @@ -1527,6 +1547,13 @@ static int __init atkbd_setup_forced_release(const struct dmi_system_id *id) return 0; } +static int __init atkbd_setup_scancode_fixup(const struct dmi_system_id *id) +{ + atkbd_platform_scancode_fixup = id->driver_data; + + return 0; +} + static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { { .ident = "Dell Laptop", @@ -1663,6 +1690,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { .callback = atkbd_setup_forced_release, .driver_data = atkdb_soltech_ta12_forced_release_keys, }, + { + .ident = "OQO Model 01+", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "OQO"), + DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"), + }, + .callback = atkbd_setup_scancode_fixup, + .driver_data = atkbd_oqo_01plus_scancode_fixup, + }, { } }; diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index a88aff3816a0..77d130914259 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -147,6 +147,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) } error = request_irq(irq, gpio_keys_isr, + IRQF_SHARED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, button->desc ? button->desc : "gpio_keys", bdata); diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 02f4f8f1db6f..a9bb2544b2de 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -227,6 +227,7 @@ config INPUT_WINBOND_CIR depends on X86 && PNP select NEW_LEDS select LEDS_CLASS + select LEDS_TRIGGERS select BITREVERSE help Say Y here if you want to use the IR remote functionality found diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index a31578170ccc..1df02d25aca5 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -836,17 +836,32 @@ static int i8042_controller_selftest(void) static int i8042_controller_init(void) { unsigned long flags; + int n = 0; + unsigned char ctr[2]; /* - * Save the CTR for restoral on unload / reboot. + * Save the CTR for restore on unload / reboot. */ - if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) { - printk(KERN_ERR "i8042.c: Can't read CTR while initializing i8042.\n"); - return -EIO; - } + do { + if (n >= 10) { + printk(KERN_ERR + "i8042.c: Unable to get stable CTR read.\n"); + return -EIO; + } + + if (n != 0) + udelay(50); + + if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) { + printk(KERN_ERR + "i8042.c: Can't read CTR while initializing i8042.\n"); + return -EIO; + } - i8042_initial_ctr = i8042_ctr; + } while (n < 2 || ctr[0] != ctr[1]); + + i8042_initial_ctr = i8042_ctr = ctr[0]; /* * Disable the keyboard interface and interrupt. @@ -895,6 +910,12 @@ static int i8042_controller_init(void) return -EIO; } +/* + * Flush whatever accumulated while we were disabling keyboard port. + */ + + i8042_flush(); + return 0; } @@ -914,7 +935,7 @@ static void i8042_controller_reset(void) i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS; i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); - if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR)) + if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) printk(KERN_WARNING "i8042.c: Can't write CTR while resetting.\n"); /* diff --git a/drivers/isdn/i4l/isdn_net.h b/drivers/isdn/i4l/isdn_net.h index 74032d0881ef..7511f08effa5 100644 --- a/drivers/isdn/i4l/isdn_net.h +++ b/drivers/isdn/i4l/isdn_net.h @@ -83,19 +83,19 @@ static __inline__ isdn_net_local * isdn_net_get_locked_lp(isdn_net_dev *nd) spin_lock_irqsave(&nd->queue_lock, flags); lp = nd->queue; /* get lp on top of queue */ - spin_lock(&nd->queue->xmit_lock); while (isdn_net_lp_busy(nd->queue)) { - spin_unlock(&nd->queue->xmit_lock); nd->queue = nd->queue->next; if (nd->queue == lp) { /* not found -- should never happen */ lp = NULL; goto errout; } - spin_lock(&nd->queue->xmit_lock); } lp = nd->queue; nd->queue = nd->queue->next; + spin_unlock_irqrestore(&nd->queue_lock, flags); + spin_lock(&lp->xmit_lock); local_bh_disable(); + return lp; errout: spin_unlock_irqrestore(&nd->queue_lock, flags); return lp; diff --git a/drivers/md/Makefile b/drivers/md/Makefile index 1dc4185bd781..e355e7f6a536 100644 --- a/drivers/md/Makefile +++ b/drivers/md/Makefile @@ -46,7 +46,7 @@ obj-$(CONFIG_DM_LOG_USERSPACE) += dm-log-userspace.o obj-$(CONFIG_DM_ZERO) += dm-zero.o quiet_cmd_unroll = UNROLL $@ - cmd_unroll = $(PERL) $(srctree)/$(src)/unroll.pl $(UNROLL) \ + cmd_unroll = $(AWK) -f$(srctree)/$(src)/unroll.awk -vN=$(UNROLL) \ < $< > $@ || ( rm -f $@ && exit 1 ) ifeq ($(CONFIG_ALTIVEC),y) @@ -59,56 +59,56 @@ endif targets += raid6int1.c $(obj)/raid6int1.c: UNROLL := 1 -$(obj)/raid6int1.c: $(src)/raid6int.uc $(src)/unroll.pl FORCE +$(obj)/raid6int1.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE $(call if_changed,unroll) targets += raid6int2.c $(obj)/raid6int2.c: UNROLL := 2 -$(obj)/raid6int2.c: $(src)/raid6int.uc $(src)/unroll.pl FORCE +$(obj)/raid6int2.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE $(call if_changed,unroll) targets += raid6int4.c $(obj)/raid6int4.c: UNROLL := 4 -$(obj)/raid6int4.c: $(src)/raid6int.uc $(src)/unroll.pl FORCE +$(obj)/raid6int4.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE $(call if_changed,unroll) targets += raid6int8.c $(obj)/raid6int8.c: UNROLL := 8 -$(obj)/raid6int8.c: $(src)/raid6int.uc $(src)/unroll.pl FORCE +$(obj)/raid6int8.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE $(call if_changed,unroll) targets += raid6int16.c $(obj)/raid6int16.c: UNROLL := 16 -$(obj)/raid6int16.c: $(src)/raid6int.uc $(src)/unroll.pl FORCE +$(obj)/raid6int16.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE $(call if_changed,unroll) targets += raid6int32.c $(obj)/raid6int32.c: UNROLL := 32 -$(obj)/raid6int32.c: $(src)/raid6int.uc $(src)/unroll.pl FORCE +$(obj)/raid6int32.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE $(call if_changed,unroll) CFLAGS_raid6altivec1.o += $(altivec_flags) targets += raid6altivec1.c $(obj)/raid6altivec1.c: UNROLL := 1 -$(obj)/raid6altivec1.c: $(src)/raid6altivec.uc $(src)/unroll.pl FORCE +$(obj)/raid6altivec1.c: $(src)/raid6altivec.uc $(src)/unroll.awk FORCE $(call if_changed,unroll) CFLAGS_raid6altivec2.o += $(altivec_flags) targets += raid6altivec2.c $(obj)/raid6altivec2.c: UNROLL := 2 -$(obj)/raid6altivec2.c: $(src)/raid6altivec.uc $(src)/unroll.pl FORCE +$(obj)/raid6altivec2.c: $(src)/raid6altivec.uc $(src)/unroll.awk FORCE $(call if_changed,unroll) CFLAGS_raid6altivec4.o += $(altivec_flags) targets += raid6altivec4.c $(obj)/raid6altivec4.c: UNROLL := 4 -$(obj)/raid6altivec4.c: $(src)/raid6altivec.uc $(src)/unroll.pl FORCE +$(obj)/raid6altivec4.c: $(src)/raid6altivec.uc $(src)/unroll.awk FORCE $(call if_changed,unroll) CFLAGS_raid6altivec8.o += $(altivec_flags) targets += raid6altivec8.c $(obj)/raid6altivec8.c: UNROLL := 8 -$(obj)/raid6altivec8.c: $(src)/raid6altivec.uc $(src)/unroll.pl FORCE +$(obj)/raid6altivec8.c: $(src)/raid6altivec.uc $(src)/unroll.awk FORCE $(call if_changed,unroll) quiet_cmd_mktable = TABLE $@ diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 6986b0059d23..60e2b322db11 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1624,10 +1624,11 @@ int bitmap_create(mddev_t *mddev) bitmap->offset = mddev->bitmap_offset; if (file) { get_file(file); - do_sync_mapping_range(file->f_mapping, 0, LLONG_MAX, - SYNC_FILE_RANGE_WAIT_BEFORE | - SYNC_FILE_RANGE_WRITE | - SYNC_FILE_RANGE_WAIT_AFTER); + /* As future accesses to this file will use bmap, + * and bypass the page cache, we must sync the file + * first. + */ + vfs_fsync(file, file->f_dentry, 1); } /* read superblock from bitmap file (this sets bitmap->chunksize) */ err = bitmap_read_sb(bitmap); diff --git a/drivers/md/md.c b/drivers/md/md.c index 26ba42a79129..10eb1fce975e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2631,7 +2631,7 @@ static void analyze_sbs(mddev_t * mddev) rdev->desc_nr = i++; rdev->raid_disk = rdev->desc_nr; set_bit(In_sync, &rdev->flags); - } else if (rdev->raid_disk >= mddev->raid_disks) { + } else if (rdev->raid_disk >= (mddev->raid_disks - min(0, mddev->delta_disks))) { rdev->raid_disk = -1; clear_bit(In_sync, &rdev->flags); } diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index d1b9bd5fd4f6..a053423785c9 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -64,7 +64,7 @@ static void * r1bio_pool_alloc(gfp_t gfp_flags, void *data) /* allocate a r1bio with room for raid_disks entries in the bios array */ r1_bio = kzalloc(size, gfp_flags); - if (!r1_bio) + if (!r1_bio && pi->mddev) unplug_slaves(pi->mddev); return r1_bio; @@ -1683,6 +1683,7 @@ static void raid1d(mddev_t *mddev) generic_make_request(bio); } } + cond_resched(); } if (unplug) unplug_slaves(mddev); @@ -1978,13 +1979,14 @@ static int run(mddev_t *mddev) conf->poolinfo = kmalloc(sizeof(*conf->poolinfo), GFP_KERNEL); if (!conf->poolinfo) goto out_no_mem; - conf->poolinfo->mddev = mddev; + conf->poolinfo->mddev = NULL; conf->poolinfo->raid_disks = mddev->raid_disks; conf->r1bio_pool = mempool_create(NR_RAID1_BIOS, r1bio_pool_alloc, r1bio_pool_free, conf->poolinfo); if (!conf->r1bio_pool) goto out_no_mem; + conf->poolinfo->mddev = mddev; spin_lock_init(&conf->device_lock); mddev->queue->queue_lock = &conf->device_lock; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 51c4c5c4d87a..c2cb7b87b440 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -68,7 +68,7 @@ static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data) /* allocate a r10bio with room for raid_disks entries in the bios array */ r10_bio = kzalloc(size, gfp_flags); - if (!r10_bio) + if (!r10_bio && conf->mddev) unplug_slaves(conf->mddev); return r10_bio; @@ -1632,6 +1632,7 @@ static void raid10d(mddev_t *mddev) generic_make_request(bio); } } + cond_resched(); } if (unplug) unplug_slaves(mddev); @@ -2095,7 +2096,6 @@ static int run(mddev_t *mddev) if (!conf->tmppage) goto out_free_conf; - conf->mddev = mddev; conf->raid_disks = mddev->raid_disks; conf->near_copies = nc; conf->far_copies = fc; @@ -2132,6 +2132,7 @@ static int run(mddev_t *mddev) goto out_free_conf; } + conf->mddev = mddev; spin_lock_init(&conf->device_lock); mddev->queue->queue_lock = &conf->device_lock; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 94829804ab7f..81abefc172d9 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -156,13 +156,16 @@ static inline int raid6_next_disk(int disk, int raid_disks) static int raid6_idx_to_slot(int idx, struct stripe_head *sh, int *count, int syndrome_disks) { - int slot; + int slot = *count; + if (sh->ddf_layout) + (*count)++; if (idx == sh->pd_idx) return syndrome_disks; if (idx == sh->qd_idx) return syndrome_disks + 1; - slot = (*count)++; + if (!sh->ddf_layout) + (*count)++; return slot; } @@ -717,7 +720,7 @@ static int set_syndrome_sources(struct page **srcs, struct stripe_head *sh) int i; for (i = 0; i < disks; i++) - srcs[i] = (void *)raid6_empty_zero_page; + srcs[i] = NULL; count = 0; i = d0_idx; @@ -727,9 +730,8 @@ static int set_syndrome_sources(struct page **srcs, struct stripe_head *sh) srcs[slot] = sh->dev[i].page; i = raid6_next_disk(i, disks); } while (i != d0_idx); - BUG_ON(count != syndrome_disks); - return count; + return syndrome_disks; } static struct dma_async_tx_descriptor * @@ -814,7 +816,7 @@ ops_run_compute6_2(struct stripe_head *sh, struct raid5_percpu *percpu) * slot number conversion for 'faila' and 'failb' */ for (i = 0; i < disks ; i++) - blocks[i] = (void *)raid6_empty_zero_page; + blocks[i] = NULL; count = 0; i = d0_idx; do { @@ -828,7 +830,6 @@ ops_run_compute6_2(struct stripe_head *sh, struct raid5_percpu *percpu) failb = slot; i = raid6_next_disk(i, disks); } while (i != d0_idx); - BUG_ON(count != syndrome_disks); BUG_ON(faila == failb); if (failb < faila) @@ -845,7 +846,7 @@ ops_run_compute6_2(struct stripe_head *sh, struct raid5_percpu *percpu) init_async_submit(&submit, ASYNC_TX_FENCE, NULL, ops_complete_compute, sh, to_addr_conv(sh, percpu)); - return async_gen_syndrome(blocks, 0, count+2, + return async_gen_syndrome(blocks, 0, syndrome_disks+2, STRIPE_SIZE, &submit); } else { struct page *dest; @@ -1139,7 +1140,7 @@ static void ops_run_check_pq(struct stripe_head *sh, struct raid5_percpu *percpu &sh->ops.zero_sum_result, percpu->spare_page, &submit); } -static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request) +static void __raid_run_ops(struct stripe_head *sh, unsigned long ops_request) { int overlap_clear = 0, i, disks = sh->disks; struct dma_async_tx_descriptor *tx = NULL; @@ -1204,22 +1205,55 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request) put_cpu(); } +#ifdef CONFIG_MULTICORE_RAID456 +static void async_run_ops(void *param, async_cookie_t cookie) +{ + struct stripe_head *sh = param; + unsigned long ops_request = sh->ops.request; + + clear_bit_unlock(STRIPE_OPS_REQ_PENDING, &sh->state); + wake_up(&sh->ops.wait_for_ops); + + __raid_run_ops(sh, ops_request); + release_stripe(sh); +} + +static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request) +{ + /* since handle_stripe can be called outside of raid5d context + * we need to ensure sh->ops.request is de-staged before another + * request arrives + */ + wait_event(sh->ops.wait_for_ops, + !test_and_set_bit_lock(STRIPE_OPS_REQ_PENDING, &sh->state)); + sh->ops.request = ops_request; + + atomic_inc(&sh->count); + async_schedule(async_run_ops, sh); +} +#else +#define raid_run_ops __raid_run_ops +#endif + static int grow_one_stripe(raid5_conf_t *conf) { struct stripe_head *sh; + int disks = max(conf->raid_disks, conf->previous_raid_disks); sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL); if (!sh) return 0; - memset(sh, 0, sizeof(*sh) + (conf->raid_disks-1)*sizeof(struct r5dev)); + memset(sh, 0, sizeof(*sh) + (disks-1)*sizeof(struct r5dev)); sh->raid_conf = conf; spin_lock_init(&sh->lock); + #ifdef CONFIG_MULTICORE_RAID456 + init_waitqueue_head(&sh->ops.wait_for_ops); + #endif - if (grow_buffers(sh, conf->raid_disks)) { - shrink_buffers(sh, conf->raid_disks); + if (grow_buffers(sh, disks)) { + shrink_buffers(sh, disks); kmem_cache_free(conf->slab_cache, sh); return 0; } - sh->disks = conf->raid_disks; /* we just created an active stripe so... */ atomic_set(&sh->count, 1); atomic_inc(&conf->active_stripes); @@ -1231,7 +1265,7 @@ static int grow_one_stripe(raid5_conf_t *conf) static int grow_stripes(raid5_conf_t *conf, int num) { struct kmem_cache *sc; - int devs = conf->raid_disks; + int devs = max(conf->raid_disks, conf->previous_raid_disks); sprintf(conf->cache_name[0], "raid%d-%s", conf->level, mdname(conf->mddev)); @@ -1329,6 +1363,9 @@ static int resize_stripes(raid5_conf_t *conf, int newsize) nsh->raid_conf = conf; spin_lock_init(&nsh->lock); + #ifdef CONFIG_MULTICORE_RAID456 + init_waitqueue_head(&nsh->ops.wait_for_ops); + #endif list_add(&nsh->lru, &newstripes); } @@ -1899,10 +1936,15 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i, int previous) case ALGORITHM_PARITY_N: break; case ALGORITHM_ROTATING_N_CONTINUE: + /* Like left_symmetric, but P is before Q */ if (sh->pd_idx == 0) i--; /* P D D D Q */ - else if (i > sh->pd_idx) - i -= 2; /* D D Q P D */ + else { + /* D D Q P D */ + if (i < sh->pd_idx) + i += raid_disks; + i -= (sh->pd_idx + 1); + } break; case ALGORITHM_LEFT_ASYMMETRIC_6: case ALGORITHM_RIGHT_ASYMMETRIC_6: @@ -2896,7 +2938,7 @@ static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh, * */ -static bool handle_stripe5(struct stripe_head *sh) +static void handle_stripe5(struct stripe_head *sh) { raid5_conf_t *conf = sh->raid_conf; int disks = sh->disks, i; @@ -3167,11 +3209,9 @@ static bool handle_stripe5(struct stripe_head *sh) ops_run_io(sh, &s); return_io(return_bi); - - return blocked_rdev == NULL; } -static bool handle_stripe6(struct stripe_head *sh) +static void handle_stripe6(struct stripe_head *sh) { raid5_conf_t *conf = sh->raid_conf; int disks = sh->disks; @@ -3455,17 +3495,14 @@ static bool handle_stripe6(struct stripe_head *sh) ops_run_io(sh, &s); return_io(return_bi); - - return blocked_rdev == NULL; } -/* returns true if the stripe was handled */ -static bool handle_stripe(struct stripe_head *sh) +static void handle_stripe(struct stripe_head *sh) { if (sh->raid_conf->level == 6) - return handle_stripe6(sh); + handle_stripe6(sh); else - return handle_stripe5(sh); + handle_stripe5(sh); } static void raid5_activate_delayed(raid5_conf_t *conf) @@ -3503,9 +3540,10 @@ static void unplug_slaves(mddev_t *mddev) { raid5_conf_t *conf = mddev->private; int i; + int devs = max(conf->raid_disks, conf->previous_raid_disks); rcu_read_lock(); - for (i = 0; i < conf->raid_disks; i++) { + for (i = 0; i < devs; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) { struct request_queue *r_queue = bdev_get_queue(rdev->bdev); @@ -4277,9 +4315,7 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski clear_bit(STRIPE_INSYNC, &sh->state); spin_unlock(&sh->lock); - /* wait for any blocked device to be handled */ - while (unlikely(!handle_stripe(sh))) - ; + handle_stripe(sh); release_stripe(sh); return STRIPE_SECTORS; @@ -4349,37 +4385,6 @@ static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio) return handled; } -#ifdef CONFIG_MULTICORE_RAID456 -static void __process_stripe(void *param, async_cookie_t cookie) -{ - struct stripe_head *sh = param; - - handle_stripe(sh); - release_stripe(sh); -} - -static void process_stripe(struct stripe_head *sh, struct list_head *domain) -{ - async_schedule_domain(__process_stripe, sh, domain); -} - -static void synchronize_stripe_processing(struct list_head *domain) -{ - async_synchronize_full_domain(domain); -} -#else -static void process_stripe(struct stripe_head *sh, struct list_head *domain) -{ - handle_stripe(sh); - release_stripe(sh); - cond_resched(); -} - -static void synchronize_stripe_processing(struct list_head *domain) -{ -} -#endif - /* * This is our raid5 kernel thread. @@ -4393,7 +4398,6 @@ static void raid5d(mddev_t *mddev) struct stripe_head *sh; raid5_conf_t *conf = mddev->private; int handled; - LIST_HEAD(raid_domain); pr_debug("+++ raid5d active\n"); @@ -4430,7 +4434,9 @@ static void raid5d(mddev_t *mddev) spin_unlock_irq(&conf->device_lock); handled++; - process_stripe(sh, &raid_domain); + handle_stripe(sh); + release_stripe(sh); + cond_resched(); spin_lock_irq(&conf->device_lock); } @@ -4438,7 +4444,6 @@ static void raid5d(mddev_t *mddev) spin_unlock_irq(&conf->device_lock); - synchronize_stripe_processing(&raid_domain); async_tx_issue_pending_all(); unplug_slaves(mddev); @@ -4558,13 +4563,9 @@ raid5_size(mddev_t *mddev, sector_t sectors, int raid_disks) if (!sectors) sectors = mddev->dev_sectors; - if (!raid_disks) { + if (!raid_disks) /* size is defined by the smallest of previous and new size */ - if (conf->raid_disks < conf->previous_raid_disks) - raid_disks = conf->raid_disks; - else - raid_disks = conf->previous_raid_disks; - } + raid_disks = min(conf->raid_disks, conf->previous_raid_disks); sectors &= ~((sector_t)mddev->chunk_sectors - 1); sectors &= ~((sector_t)mddev->new_chunk_sectors - 1); @@ -4665,7 +4666,7 @@ static int raid5_alloc_percpu(raid5_conf_t *conf) } per_cpu_ptr(conf->percpu, cpu)->spare_page = spare_page; } - scribble = kmalloc(scribble_len(conf->raid_disks), GFP_KERNEL); + scribble = kmalloc(conf->scribble_len, GFP_KERNEL); if (!scribble) { err = -ENOMEM; break; @@ -4686,7 +4687,7 @@ static int raid5_alloc_percpu(raid5_conf_t *conf) static raid5_conf_t *setup_conf(mddev_t *mddev) { raid5_conf_t *conf; - int raid_disk, memory; + int raid_disk, memory, max_disks; mdk_rdev_t *rdev; struct disk_info *disk; @@ -4722,15 +4723,28 @@ static raid5_conf_t *setup_conf(mddev_t *mddev) conf = kzalloc(sizeof(raid5_conf_t), GFP_KERNEL); if (conf == NULL) goto abort; + spin_lock_init(&conf->device_lock); + init_waitqueue_head(&conf->wait_for_stripe); + init_waitqueue_head(&conf->wait_for_overlap); + INIT_LIST_HEAD(&conf->handle_list); + INIT_LIST_HEAD(&conf->hold_list); + INIT_LIST_HEAD(&conf->delayed_list); + INIT_LIST_HEAD(&conf->bitmap_list); + INIT_LIST_HEAD(&conf->inactive_list); + atomic_set(&conf->active_stripes, 0); + atomic_set(&conf->preread_active_stripes, 0); + atomic_set(&conf->active_aligned_reads, 0); + conf->bypass_threshold = BYPASS_THRESHOLD; conf->raid_disks = mddev->raid_disks; - conf->scribble_len = scribble_len(conf->raid_disks); if (mddev->reshape_position == MaxSector) conf->previous_raid_disks = mddev->raid_disks; else conf->previous_raid_disks = mddev->raid_disks - mddev->delta_disks; + max_disks = max(conf->raid_disks, conf->previous_raid_disks); + conf->scribble_len = scribble_len(max_disks); - conf->disks = kzalloc(conf->raid_disks * sizeof(struct disk_info), + conf->disks = kzalloc(max_disks * sizeof(struct disk_info), GFP_KERNEL); if (!conf->disks) goto abort; @@ -4744,24 +4758,11 @@ static raid5_conf_t *setup_conf(mddev_t *mddev) if (raid5_alloc_percpu(conf) != 0) goto abort; - spin_lock_init(&conf->device_lock); - init_waitqueue_head(&conf->wait_for_stripe); - init_waitqueue_head(&conf->wait_for_overlap); - INIT_LIST_HEAD(&conf->handle_list); - INIT_LIST_HEAD(&conf->hold_list); - INIT_LIST_HEAD(&conf->delayed_list); - INIT_LIST_HEAD(&conf->bitmap_list); - INIT_LIST_HEAD(&conf->inactive_list); - atomic_set(&conf->active_stripes, 0); - atomic_set(&conf->preread_active_stripes, 0); - atomic_set(&conf->active_aligned_reads, 0); - conf->bypass_threshold = BYPASS_THRESHOLD; - pr_debug("raid5: run(%s) called.\n", mdname(mddev)); list_for_each_entry(rdev, &mddev->disks, same_set) { raid_disk = rdev->raid_disk; - if (raid_disk >= conf->raid_disks + if (raid_disk >= max_disks || raid_disk < 0) continue; disk = conf->disks + raid_disk; @@ -4793,7 +4794,7 @@ static raid5_conf_t *setup_conf(mddev_t *mddev) } memory = conf->max_nr_stripes * (sizeof(struct stripe_head) + - conf->raid_disks * ((sizeof(struct bio) + PAGE_SIZE))) / 1024; + max_disks * ((sizeof(struct bio) + PAGE_SIZE))) / 1024; if (grow_stripes(conf, conf->max_nr_stripes)) { printk(KERN_ERR "raid5: couldn't allocate %dkB for buffers\n", memory); @@ -4918,7 +4919,8 @@ static int run(mddev_t *mddev) test_bit(In_sync, &rdev->flags)) working_disks++; - mddev->degraded = conf->raid_disks - working_disks; + mddev->degraded = (max(conf->raid_disks, conf->previous_raid_disks) + - working_disks); if (mddev->degraded > conf->max_degraded) { printk(KERN_ERR "raid5: not enough operational devices for %s" diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h index 2390e0e83daf..dd708359b451 100644 --- a/drivers/md/raid5.h +++ b/drivers/md/raid5.h @@ -214,12 +214,20 @@ struct stripe_head { int disks; /* disks in stripe */ enum check_states check_state; enum reconstruct_states reconstruct_state; - /* stripe_operations + /** + * struct stripe_operations * @target - STRIPE_OP_COMPUTE_BLK target + * @target2 - 2nd compute target in the raid6 case + * @zero_sum_result - P and Q verification flags + * @request - async service request flags for raid_run_ops */ struct stripe_operations { int target, target2; enum sum_check_flags zero_sum_result; + #ifdef CONFIG_MULTICORE_RAID456 + unsigned long request; + wait_queue_head_t wait_for_ops; + #endif } ops; struct r5dev { struct bio req; @@ -294,6 +302,8 @@ struct r6_state { #define STRIPE_FULL_WRITE 13 /* all blocks are set to be overwritten */ #define STRIPE_BIOFILL_RUN 14 #define STRIPE_COMPUTE_RUN 15 +#define STRIPE_OPS_REQ_PENDING 16 + /* * Operation request flags */ @@ -478,7 +488,7 @@ static inline int algorithm_valid_raid6(int layout) { return (layout >= 0 && layout <= 5) || - (layout == 8 || layout == 10) + (layout >= 8 && layout <= 10) || (layout >= 16 && layout <= 20); } diff --git a/drivers/md/raid6altivec.uc b/drivers/md/raid6altivec.uc index 699dfeee4944..2654d5c854be 100644 --- a/drivers/md/raid6altivec.uc +++ b/drivers/md/raid6altivec.uc @@ -15,7 +15,7 @@ * * $#-way unrolled portable integer math RAID-6 instruction set * - * This file is postprocessed using unroll.pl + * This file is postprocessed using unroll.awk * * <benh> hpa: in process, * you can just "steal" the vec unit with enable_kernel_altivec() (but diff --git a/drivers/md/raid6int.uc b/drivers/md/raid6int.uc index f9bf9cba357f..d1e276a14fab 100644 --- a/drivers/md/raid6int.uc +++ b/drivers/md/raid6int.uc @@ -15,7 +15,7 @@ * * $#-way unrolled portable integer math RAID-6 instruction set * - * This file is postprocessed using unroll.pl + * This file is postprocessed using unroll.awk */ #include <linux/raid/pq.h> diff --git a/drivers/md/raid6test/Makefile b/drivers/md/raid6test/Makefile index 58ffdf4f5161..2874cbef529d 100644 --- a/drivers/md/raid6test/Makefile +++ b/drivers/md/raid6test/Makefile @@ -7,7 +7,7 @@ CC = gcc OPTFLAGS = -O2 # Adjust as desired CFLAGS = -I.. -I ../../../include -g $(OPTFLAGS) LD = ld -PERL = perl +AWK = awk AR = ar RANLIB = ranlib @@ -35,35 +35,35 @@ raid6.a: raid6int1.o raid6int2.o raid6int4.o raid6int8.o raid6int16.o \ raid6test: test.c raid6.a $(CC) $(CFLAGS) -o raid6test $^ -raid6altivec1.c: raid6altivec.uc ../unroll.pl - $(PERL) ../unroll.pl 1 < raid6altivec.uc > $@ +raid6altivec1.c: raid6altivec.uc ../unroll.awk + $(AWK) ../unroll.awk -vN=1 < raid6altivec.uc > $@ -raid6altivec2.c: raid6altivec.uc ../unroll.pl - $(PERL) ../unroll.pl 2 < raid6altivec.uc > $@ +raid6altivec2.c: raid6altivec.uc ../unroll.awk + $(AWK) ../unroll.awk -vN=2 < raid6altivec.uc > $@ -raid6altivec4.c: raid6altivec.uc ../unroll.pl - $(PERL) ../unroll.pl 4 < raid6altivec.uc > $@ +raid6altivec4.c: raid6altivec.uc ../unroll.awk + $(AWK) ../unroll.awk -vN=4 < raid6altivec.uc > $@ -raid6altivec8.c: raid6altivec.uc ../unroll.pl - $(PERL) ../unroll.pl 8 < raid6altivec.uc > $@ +raid6altivec8.c: raid6altivec.uc ../unroll.awk + $(AWK) ../unroll.awk -vN=8 < raid6altivec.uc > $@ -raid6int1.c: raid6int.uc ../unroll.pl - $(PERL) ../unroll.pl 1 < raid6int.uc > $@ +raid6int1.c: raid6int.uc ../unroll.awk + $(AWK) ../unroll.awk -vN=1 < raid6int.uc > $@ -raid6int2.c: raid6int.uc ../unroll.pl - $(PERL) ../unroll.pl 2 < raid6int.uc > $@ +raid6int2.c: raid6int.uc ../unroll.awk + $(AWK) ../unroll.awk -vN=2 < raid6int.uc > $@ -raid6int4.c: raid6int.uc ../unroll.pl - $(PERL) ../unroll.pl 4 < raid6int.uc > $@ +raid6int4.c: raid6int.uc ../unroll.awk + $(AWK) ../unroll.awk -vN=4 < raid6int.uc > $@ -raid6int8.c: raid6int.uc ../unroll.pl - $(PERL) ../unroll.pl 8 < raid6int.uc > $@ +raid6int8.c: raid6int.uc ../unroll.awk + $(AWK) ../unroll.awk -vN=8 < raid6int.uc > $@ -raid6int16.c: raid6int.uc ../unroll.pl - $(PERL) ../unroll.pl 16 < raid6int.uc > $@ +raid6int16.c: raid6int.uc ../unroll.awk + $(AWK) ../unroll.awk -vN=16 < raid6int.uc > $@ -raid6int32.c: raid6int.uc ../unroll.pl - $(PERL) ../unroll.pl 32 < raid6int.uc > $@ +raid6int32.c: raid6int.uc ../unroll.awk + $(AWK) ../unroll.awk -vN=32 < raid6int.uc > $@ raid6tables.c: mktables ./mktables > raid6tables.c diff --git a/drivers/md/unroll.awk b/drivers/md/unroll.awk new file mode 100644 index 000000000000..c6aa03631df8 --- /dev/null +++ b/drivers/md/unroll.awk @@ -0,0 +1,20 @@ + +# This filter requires one command line option of form -vN=n +# where n must be a decimal number. +# +# Repeat each input line containing $$ n times, replacing $$ with 0...n-1. +# Replace each $# with n, and each $* with a single $. + +BEGIN { + n = N + 0 +} +{ + if (/\$\$/) { rep = n } else { rep = 1 } + for (i = 0; i < rep; ++i) { + tmp = $0 + gsub(/\$\$/, i, tmp) + gsub(/\$\#/, n, tmp) + gsub(/\$\*/, "$", tmp) + print tmp + } +} diff --git a/drivers/md/unroll.pl b/drivers/md/unroll.pl deleted file mode 100644 index 3acc710a20ea..000000000000 --- a/drivers/md/unroll.pl +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/perl -# -# Take a piece of C code and for each line which contains the sequence $$ -# repeat n times with $ replaced by 0...n-1; the sequence $# is replaced -# by the unrolling factor, and $* with a single $ -# - -($n) = @ARGV; -$n += 0; - -while ( defined($line = <STDIN>) ) { - if ( $line =~ /\$\$/ ) { - $rep = $n; - } else { - $rep = 1; - } - for ( $i = 0 ; $i < $rep ; $i++ ) { - $tmp = $line; - $tmp =~ s/\$\$/$i/g; - $tmp =~ s/\$\#/$n/g; - $tmp =~ s/\$\*/\$/g; - print $tmp; - } -} diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl4030-core.c index e832e975da60..a1c47ee95c0e 100644 --- a/drivers/mfd/twl4030-core.c +++ b/drivers/mfd/twl4030-core.c @@ -795,7 +795,7 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id) twl->client = i2c_new_dummy(client->adapter, twl->address); if (!twl->client) { - dev_err(&twl->client->dev, + dev_err(&client->dev, "can't attach client %d\n", i); status = -ENOMEM; goto fail; diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c index d3015dfb9134..ac056ea6b66e 100644 --- a/drivers/mfd/wm831x-irq.c +++ b/drivers/mfd/wm831x-irq.c @@ -507,6 +507,8 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) { int i, ret; + mutex_init(&wm831x->irq_lock); + if (!irq) { dev_warn(wm831x->dev, "No interrupt specified - functionality limited\n"); @@ -521,7 +523,6 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) } wm831x->irq = irq; - mutex_init(&wm831x->irq_lock); INIT_WORK(&wm831x->irq_work, wm831x_irq_worker); /* Mask the individual interrupt sources */ diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 4487cc097911..0aecaaebef3d 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2013,7 +2013,7 @@ static struct platform_driver omap_hsmmc_driver = { static int __init omap_hsmmc_init(void) { /* Register the MMC driver */ - return platform_driver_register(&omap_hsmmc_driver); + return platform_driver_probe(&omap_hsmmc_driver, omap_hsmmc_probe); } static void __exit omap_hsmmc_cleanup(void) diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index e1f7d0a78b9d..14cec04c34f9 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -42,6 +42,7 @@ #include <linux/log2.h> #include <linux/kthread.h> #include <linux/reboot.h> +#include <linux/kernel.h> #include "ubi.h" /* Maximum length of the 'mtd=' parameter */ @@ -1257,7 +1258,7 @@ static int __init bytes_str_to_int(const char *str) unsigned long result; result = simple_strtoul(str, &endp, 0); - if (str == endp || result < 0) { + if (str == endp || result >= INT_MAX) { printk(KERN_ERR "UBI error: incorrect bytes count: \"%s\"\n", str); return -EINVAL; diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index e7161adc419d..90af61a2c3e4 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -794,16 +794,15 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, * number. */ image_seq = be32_to_cpu(ech->image_seq); - if (!si->image_seq_set) { + if (!ubi->image_seq && image_seq) ubi->image_seq = image_seq; - si->image_seq_set = 1; - } else if (ubi->image_seq && ubi->image_seq != image_seq) { + if (ubi->image_seq && image_seq && + ubi->image_seq != image_seq) { ubi_err("bad image sequence number %d in PEB %d, " "expected %d", image_seq, pnum, ubi->image_seq); ubi_dbg_dump_ec_hdr(ech); return -EINVAL; } - } /* OK, we've done with the EC header, let's look at the VID header */ diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h index bab31695dace..ff179ad7ca55 100644 --- a/drivers/mtd/ubi/scan.h +++ b/drivers/mtd/ubi/scan.h @@ -103,7 +103,6 @@ struct ubi_scan_volume { * @ec_sum: a temporary variable used when calculating @mean_ec * @ec_count: a temporary variable used when calculating @mean_ec * @corr_count: count of corrupted PEBs - * @image_seq_set: indicates @ubi->image_seq is known * * This data structure contains the result of scanning and may be used by other * UBI sub-systems to build final UBI data structures, further error-recovery @@ -127,7 +126,6 @@ struct ubi_scan_info { uint64_t ec_sum; int ec_count; int corr_count; - int image_seq_set; }; struct ubi_device; diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index 04f63c77071d..ce6f1ac25df8 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -34,6 +34,7 @@ * * */ +#include <linux/capability.h> #include <linux/dma-mapping.h> #include <linux/module.h> #include <linux/kernel.h> diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 6c7f795d12de..a4d83409f205 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -361,9 +361,12 @@ struct l2_fhdr { #define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE (1<<28) #define BNX2_L2CTX_HOST_BDIDX 0x00000004 -#define BNX2_L2CTX_STATUSB_NUM_SHIFT 16 -#define BNX2_L2CTX_STATUSB_NUM(sb_id) \ - (((sb_id) > 0) ? (((sb_id) + 7) << BNX2_L2CTX_STATUSB_NUM_SHIFT) : 0) +#define BNX2_L2CTX_L5_STATUSB_NUM_SHIFT 16 +#define BNX2_L2CTX_L2_STATUSB_NUM_SHIFT 24 +#define BNX2_L2CTX_L5_STATUSB_NUM(sb_id) \ + (((sb_id) > 0) ? (((sb_id) + 7) << BNX2_L2CTX_L5_STATUSB_NUM_SHIFT) : 0) +#define BNX2_L2CTX_L2_STATUSB_NUM(sb_id) \ + (((sb_id) > 0) ? (((sb_id) + 7) << BNX2_L2CTX_L2_STATUSB_NUM_SHIFT) : 0) #define BNX2_L2CTX_HOST_BSEQ 0x00000008 #define BNX2_L2CTX_NX_BSEQ 0x0000000c #define BNX2_L2CTX_NX_BDHADDR_HI 0x00000010 diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 69c5b15e22da..40fb5eefc72e 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -691,7 +691,7 @@ static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_dev, int reporting) { const struct net_device_ops *slave_ops = slave_dev->netdev_ops; - static int (*ioctl)(struct net_device *, struct ifreq *, int); + int (*ioctl)(struct net_device *, struct ifreq *, int); struct ifreq ifr; struct mii_ioctl_data *mii; @@ -3665,10 +3665,10 @@ static int bond_xmit_hash_policy_l23(struct sk_buff *skb, if (skb->protocol == htons(ETH_P_IP)) { return ((ntohl(iph->saddr ^ iph->daddr) & 0xffff) ^ - (data->h_dest[5] ^ bond_dev->dev_addr[5])) % count; + (data->h_dest[5] ^ data->h_source[5])) % count; } - return (data->h_dest[5] ^ bond_dev->dev_addr[5]) % count; + return (data->h_dest[5] ^ data->h_source[5]) % count; } /* @@ -3695,7 +3695,7 @@ static int bond_xmit_hash_policy_l34(struct sk_buff *skb, } - return (data->h_dest[5] ^ bond_dev->dev_addr[5]) % count; + return (data->h_dest[5] ^ data->h_source[5]) % count; } /* @@ -3706,7 +3706,7 @@ static int bond_xmit_hash_policy_l2(struct sk_buff *skb, { struct ethhdr *data = (struct ethhdr *)skb->data; - return (data->h_dest[5] ^ bond_dev->dev_addr[5]) % count; + return (data->h_dest[5] ^ data->h_source[5]) % count; } /*-------------------------- Device entry points ----------------------------*/ diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 46c87ec7960c..3bf1b04f2cab 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -2264,9 +2264,9 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev) cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_CTX_TYPE, val); if (sb_id == 0) - val = 2 << BNX2_L2CTX_STATUSB_NUM_SHIFT; + val = 2 << BNX2_L2CTX_L2_STATUSB_NUM_SHIFT; else - val = BNX2_L2CTX_STATUSB_NUM(sb_id); + val = BNX2_L2CTX_L2_STATUSB_NUM(sb_id); cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_HOST_BDIDX, val); rxbd = (struct rx_bd *) (cp->l2_ring + BCM_PAGE_SIZE); @@ -2423,7 +2423,7 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev) cp->int_num = 0; if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) { u32 sb_id = cp->status_blk_num; - u32 sb = BNX2_L2CTX_STATUSB_NUM(sb_id); + u32 sb = BNX2_L2CTX_L5_STATUSB_NUM(sb_id); cp->int_num = sb_id << BNX2_PCICFG_INT_ACK_CMD_INT_NUM_SHIFT; cnic_ctx_wr(dev, cp->kwq_cid_addr, L5_KRNLQ_HOST_QIDX, sb); diff --git a/drivers/net/dm9000.h b/drivers/net/dm9000.h index 80817c2edfb3..fb1c924d79b4 100644 --- a/drivers/net/dm9000.h +++ b/drivers/net/dm9000.h @@ -50,7 +50,7 @@ #define DM9000_RCSR 0x32 #define CHIPR_DM9000A 0x19 -#define CHIPR_DM9000B 0x1B +#define CHIPR_DM9000B 0x1A #define DM9000_MRCMDX 0xF0 #define DM9000_MRCMD 0xF2 diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 5d2f48f02251..3c29a20b751e 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1427,19 +1427,31 @@ static int e100_phy_init(struct nic *nic) } else DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - /* Isolate all the PHY ids */ - for (addr = 0; addr < 32; addr++) - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - /* Select the discovered PHY */ - bmcr &= ~BMCR_ISOLATE; - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); - /* Get phy ID */ id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); nic->phy = (u32)id_hi << 16 | (u32)id_lo; DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); + /* Select the phy and isolate the rest */ + for (addr = 0; addr < 32; addr++) { + if (addr != nic->mii.phy_id) { + mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); + } else if (nic->phy != phy_82552_v) { + bmcr = mdio_read(netdev, addr, MII_BMCR); + mdio_write(netdev, addr, MII_BMCR, + bmcr & ~BMCR_ISOLATE); + } + } + /* + * Workaround for 82552: + * Clear the ISOLATE bit on selected phy_id last (mirrored on all + * other phy_id's) using bmcr value from addr discovery loop above. + */ + if (nic->phy == phy_82552_v) + mdio_write(netdev, nic->mii.phy_id, MII_BMCR, + bmcr & ~BMCR_ISOLATE); + /* Handle National tx phys */ #define NCS_PHY_MODEL_MASK 0xFFF0FFFF if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index c0f185beb8bc..1190167a8b3d 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h @@ -76,6 +76,7 @@ /* Extended Device Control */ #define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Definable Pin 7 */ #define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ +#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */ #define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */ #define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clock Gating */ #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 @@ -347,6 +348,7 @@ /* Extended Configuration Control and Size */ #define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020 #define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001 +#define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE 0x00000008 #define E1000_EXTCNF_CTRL_SWFLAG 0x00000020 #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK 0x00FF0000 #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT 16 diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 981936c1fb46..189dfa2d6c76 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -141,6 +141,20 @@ struct e1000_info; #define HV_TNCRS_UPPER PHY_REG(778, 29) /* Transmit with no CRS */ #define HV_TNCRS_LOWER PHY_REG(778, 30) +/* BM PHY Copper Specific Status */ +#define BM_CS_STATUS 17 +#define BM_CS_STATUS_LINK_UP 0x0400 +#define BM_CS_STATUS_RESOLVED 0x0800 +#define BM_CS_STATUS_SPEED_MASK 0xC000 +#define BM_CS_STATUS_SPEED_1000 0x8000 + +/* 82577 Mobile Phy Status Register */ +#define HV_M_STATUS 26 +#define HV_M_STATUS_AUTONEG_COMPLETE 0x1000 +#define HV_M_STATUS_SPEED_MASK 0x0300 +#define HV_M_STATUS_SPEED_1000 0x0200 +#define HV_M_STATUS_LINK_UP 0x0040 + enum e1000_boards { board_82571, board_82572, @@ -519,9 +533,13 @@ extern s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw); extern s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw); extern s32 e1000e_get_phy_info_igp(struct e1000_hw *hw); extern s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data); +extern s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, + u16 *data); extern s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw); extern s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active); extern s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data); +extern s32 e1000e_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, + u16 data); extern s32 e1000e_phy_sw_reset(struct e1000_hw *hw); extern s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw); extern s32 e1000e_get_cfg_done(struct e1000_hw *hw); @@ -538,7 +556,11 @@ extern s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data); extern s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data); extern void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl); extern s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data); +extern s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, + u16 data); extern s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data); +extern s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, + u16 *data); extern s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, u32 usec_interval, bool *success); extern s32 e1000e_phy_reset_dsp(struct e1000_hw *hw); @@ -546,7 +568,11 @@ extern s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); extern s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); extern s32 e1000e_check_downshift(struct e1000_hw *hw); extern s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data); +extern s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, + u16 *data); extern s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data); +extern s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, + u16 data); extern s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow); extern s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw); extern s32 e1000_copper_link_setup_82577(struct e1000_hw *hw); diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index fd44d9f90769..aaea41ef794d 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -764,11 +764,13 @@ struct e1000_phy_operations { s32 (*get_cable_length)(struct e1000_hw *); s32 (*get_phy_info)(struct e1000_hw *); s32 (*read_phy_reg)(struct e1000_hw *, u32, u16 *); + s32 (*read_phy_reg_locked)(struct e1000_hw *, u32, u16 *); void (*release_phy)(struct e1000_hw *); s32 (*reset_phy)(struct e1000_hw *); s32 (*set_d0_lplu_state)(struct e1000_hw *, bool); s32 (*set_d3_lplu_state)(struct e1000_hw *, bool); s32 (*write_phy_reg)(struct e1000_hw *, u32, u16); + s32 (*write_phy_reg_locked)(struct e1000_hw *, u32, u16); s32 (*cfg_on_link_up)(struct e1000_hw *); }; @@ -901,6 +903,7 @@ struct e1000_shadow_ram { struct e1000_dev_spec_ich8lan { bool kmrn_lock_loss_workaround_enabled; struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS]; + bool nvm_k1_enabled; }; struct e1000_hw { diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 99df2abf82a9..51ddb04ab195 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -122,6 +122,27 @@ #define HV_LED_CONFIG PHY_REG(768, 30) /* LED Configuration */ +#define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in milliseconds */ + +/* SMBus Address Phy Register */ +#define HV_SMB_ADDR PHY_REG(768, 26) +#define HV_SMB_ADDR_PEC_EN 0x0200 +#define HV_SMB_ADDR_VALID 0x0080 + +/* Strapping Option Register - RO */ +#define E1000_STRAP 0x0000C +#define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000 +#define E1000_STRAP_SMBUS_ADDRESS_SHIFT 17 + +/* OEM Bits Phy Register */ +#define HV_OEM_BITS PHY_REG(768, 25) +#define HV_OEM_BITS_LPLU 0x0004 /* Low Power Link Up */ +#define HV_OEM_BITS_GBE_DIS 0x0040 /* Gigabit Disable */ +#define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */ + +#define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */ +#define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */ + /* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ /* Offset 04h HSFSTS */ union ich8_hws_flash_status { @@ -200,6 +221,10 @@ static s32 e1000_setup_led_pchlan(struct e1000_hw *hw); static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw); static s32 e1000_led_on_pchlan(struct e1000_hw *hw); static s32 e1000_led_off_pchlan(struct e1000_hw *hw); +static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active); +static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw); +static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link); +static s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable); static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg) { @@ -242,7 +267,11 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) phy->ops.check_polarity = e1000_check_polarity_ife_ich8lan; phy->ops.read_phy_reg = e1000_read_phy_reg_hv; + phy->ops.read_phy_reg_locked = e1000_read_phy_reg_hv_locked; + phy->ops.set_d0_lplu_state = e1000_set_lplu_state_pchlan; + phy->ops.set_d3_lplu_state = e1000_set_lplu_state_pchlan; phy->ops.write_phy_reg = e1000_write_phy_reg_hv; + phy->ops.write_phy_reg_locked = e1000_write_phy_reg_hv_locked; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; phy->id = e1000_phy_unknown; @@ -303,6 +332,8 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) case IGP03E1000_E_PHY_ID: phy->type = e1000_phy_igp_3; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; + phy->ops.read_phy_reg_locked = e1000e_read_phy_reg_igp_locked; + phy->ops.write_phy_reg_locked = e1000e_write_phy_reg_igp_locked; break; case IFE_E_PHY_ID: case IFE_PLUS_E_PHY_ID: @@ -469,14 +500,6 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) goto out; } - if (hw->mac.type == e1000_pchlan) { - ret_val = e1000e_write_kmrn_reg(hw, - E1000_KMRNCTRLSTA_K1_CONFIG, - E1000_KMRNCTRLSTA_K1_ENABLE); - if (ret_val) - goto out; - } - /* * First we want to see if the MII Status Register reports * link. If so, then we want to get the current speed/duplex @@ -486,6 +509,12 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) if (ret_val) goto out; + if (hw->mac.type == e1000_pchlan) { + ret_val = e1000_k1_gig_workaround_hv(hw, link); + if (ret_val) + goto out; + } + if (!link) goto out; /* No link detected */ @@ -568,12 +597,39 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) static DEFINE_MUTEX(nvm_mutex); /** + * e1000_acquire_nvm_ich8lan - Acquire NVM mutex + * @hw: pointer to the HW structure + * + * Acquires the mutex for performing NVM operations. + **/ +static s32 e1000_acquire_nvm_ich8lan(struct e1000_hw *hw) +{ + mutex_lock(&nvm_mutex); + + return 0; +} + +/** + * e1000_release_nvm_ich8lan - Release NVM mutex + * @hw: pointer to the HW structure + * + * Releases the mutex used while performing NVM operations. + **/ +static void e1000_release_nvm_ich8lan(struct e1000_hw *hw) +{ + mutex_unlock(&nvm_mutex); + + return; +} + +static DEFINE_MUTEX(swflag_mutex); + +/** * e1000_acquire_swflag_ich8lan - Acquire software control flag * @hw: pointer to the HW structure * - * Acquires the software control flag for performing NVM and PHY - * operations. This is a function pointer entry point only called by - * read/write routines for the PHY and NVM parts. + * Acquires the software control flag for performing PHY and select + * MAC CSR accesses. **/ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) { @@ -582,7 +638,7 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) might_sleep(); - mutex_lock(&nvm_mutex); + mutex_lock(&swflag_mutex); while (timeout) { extcnf_ctrl = er32(EXTCNF_CTRL); @@ -599,7 +655,7 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) goto out; } - timeout = PHY_CFG_TIMEOUT * 2; + timeout = SW_FLAG_TIMEOUT; extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG; ew32(EXTCNF_CTRL, extcnf_ctrl); @@ -623,7 +679,7 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) out: if (ret_val) - mutex_unlock(&nvm_mutex); + mutex_unlock(&swflag_mutex); return ret_val; } @@ -632,9 +688,8 @@ out: * e1000_release_swflag_ich8lan - Release software control flag * @hw: pointer to the HW structure * - * Releases the software control flag for performing NVM and PHY operations. - * This is a function pointer entry point only called by read/write - * routines for the PHY and NVM parts. + * Releases the software control flag for performing PHY and select + * MAC CSR accesses. **/ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw) { @@ -644,7 +699,9 @@ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw) extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; ew32(EXTCNF_CTRL, extcnf_ctrl); - mutex_unlock(&nvm_mutex); + mutex_unlock(&swflag_mutex); + + return; } /** @@ -752,6 +809,326 @@ static s32 e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw) } /** + * e1000_sw_lcd_config_ich8lan - SW-based LCD Configuration + * @hw: pointer to the HW structure + * + * SW should configure the LCD from the NVM extended configuration region + * as a workaround for certain parts. + **/ +static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask; + s32 ret_val; + u16 word_addr, reg_data, reg_addr, phy_page = 0; + + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) + return ret_val; + + /* + * Initialize the PHY from the NVM on ICH platforms. This + * is needed due to an issue where the NVM configuration is + * not properly autoloaded after power transitions. + * Therefore, after each PHY reset, we will load the + * configuration data out of the NVM manually. + */ + if ((hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) || + (hw->mac.type == e1000_pchlan)) { + struct e1000_adapter *adapter = hw->adapter; + + /* Check if SW needs to configure the PHY */ + if ((adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M_AMT) || + (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M) || + (hw->mac.type == e1000_pchlan)) + sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; + else + sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG; + + data = er32(FEXTNVM); + if (!(data & sw_cfg_mask)) + goto out; + + /* Wait for basic configuration completes before proceeding */ + e1000_lan_init_done_ich8lan(hw); + + /* + * Make sure HW does not configure LCD from PHY + * extended configuration before SW configuration + */ + data = er32(EXTCNF_CTRL); + if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) + goto out; + + cnf_size = er32(EXTCNF_SIZE); + cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK; + cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT; + if (!cnf_size) + goto out; + + cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK; + cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; + + if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) && + (hw->mac.type == e1000_pchlan)) { + /* + * HW configures the SMBus address and LEDs when the + * OEM and LCD Write Enable bits are set in the NVM. + * When both NVM bits are cleared, SW will configure + * them instead. + */ + data = er32(STRAP); + data &= E1000_STRAP_SMBUS_ADDRESS_MASK; + reg_data = data >> E1000_STRAP_SMBUS_ADDRESS_SHIFT; + reg_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID; + ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, + reg_data); + if (ret_val) + goto out; + + data = er32(LEDCTL); + ret_val = e1000_write_phy_reg_hv_locked(hw, + HV_LED_CONFIG, + (u16)data); + if (ret_val) + goto out; + } + /* Configure LCD from extended configuration region. */ + + /* cnf_base_addr is in DWORD */ + word_addr = (u16)(cnf_base_addr << 1); + + for (i = 0; i < cnf_size; i++) { + ret_val = e1000_read_nvm(hw, (word_addr + i * 2), 1, + ®_data); + if (ret_val) + goto out; + + ret_val = e1000_read_nvm(hw, (word_addr + i * 2 + 1), + 1, ®_addr); + if (ret_val) + goto out; + + /* Save off the PHY page for future writes. */ + if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) { + phy_page = reg_data; + continue; + } + + reg_addr &= PHY_REG_MASK; + reg_addr |= phy_page; + + ret_val = phy->ops.write_phy_reg_locked(hw, + (u32)reg_addr, + reg_data); + if (ret_val) + goto out; + } + } + +out: + hw->phy.ops.release_phy(hw); + return ret_val; +} + +/** + * e1000_k1_gig_workaround_hv - K1 Si workaround + * @hw: pointer to the HW structure + * @link: link up bool flag + * + * If K1 is enabled for 1Gbps, the MAC might stall when transitioning + * from a lower speed. This workaround disables K1 whenever link is at 1Gig + * If link is down, the function will restore the default K1 setting located + * in the NVM. + **/ +static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link) +{ + s32 ret_val = 0; + u16 status_reg = 0; + bool k1_enable = hw->dev_spec.ich8lan.nvm_k1_enabled; + + if (hw->mac.type != e1000_pchlan) + goto out; + + /* Wrap the whole flow with the sw flag */ + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) + goto out; + + /* Disable K1 when link is 1Gbps, otherwise use the NVM setting */ + if (link) { + if (hw->phy.type == e1000_phy_82578) { + ret_val = hw->phy.ops.read_phy_reg_locked(hw, + BM_CS_STATUS, + &status_reg); + if (ret_val) + goto release; + + status_reg &= BM_CS_STATUS_LINK_UP | + BM_CS_STATUS_RESOLVED | + BM_CS_STATUS_SPEED_MASK; + + if (status_reg == (BM_CS_STATUS_LINK_UP | + BM_CS_STATUS_RESOLVED | + BM_CS_STATUS_SPEED_1000)) + k1_enable = false; + } + + if (hw->phy.type == e1000_phy_82577) { + ret_val = hw->phy.ops.read_phy_reg_locked(hw, + HV_M_STATUS, + &status_reg); + if (ret_val) + goto release; + + status_reg &= HV_M_STATUS_LINK_UP | + HV_M_STATUS_AUTONEG_COMPLETE | + HV_M_STATUS_SPEED_MASK; + + if (status_reg == (HV_M_STATUS_LINK_UP | + HV_M_STATUS_AUTONEG_COMPLETE | + HV_M_STATUS_SPEED_1000)) + k1_enable = false; + } + + /* Link stall fix for link up */ + ret_val = hw->phy.ops.write_phy_reg_locked(hw, PHY_REG(770, 19), + 0x0100); + if (ret_val) + goto release; + + } else { + /* Link stall fix for link down */ + ret_val = hw->phy.ops.write_phy_reg_locked(hw, PHY_REG(770, 19), + 0x4100); + if (ret_val) + goto release; + } + + ret_val = e1000_configure_k1_ich8lan(hw, k1_enable); + +release: + hw->phy.ops.release_phy(hw); +out: + return ret_val; +} + +/** + * e1000_configure_k1_ich8lan - Configure K1 power state + * @hw: pointer to the HW structure + * @enable: K1 state to configure + * + * Configure the K1 power state based on the provided parameter. + * Assumes semaphore already acquired. + * + * Success returns 0, Failure returns -E1000_ERR_PHY (-2) + **/ +static s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable) +{ + s32 ret_val = 0; + u32 ctrl_reg = 0; + u32 ctrl_ext = 0; + u32 reg = 0; + u16 kmrn_reg = 0; + + ret_val = e1000e_read_kmrn_reg_locked(hw, + E1000_KMRNCTRLSTA_K1_CONFIG, + &kmrn_reg); + if (ret_val) + goto out; + + if (k1_enable) + kmrn_reg |= E1000_KMRNCTRLSTA_K1_ENABLE; + else + kmrn_reg &= ~E1000_KMRNCTRLSTA_K1_ENABLE; + + ret_val = e1000e_write_kmrn_reg_locked(hw, + E1000_KMRNCTRLSTA_K1_CONFIG, + kmrn_reg); + if (ret_val) + goto out; + + udelay(20); + ctrl_ext = er32(CTRL_EXT); + ctrl_reg = er32(CTRL); + + reg = ctrl_reg & ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); + reg |= E1000_CTRL_FRCSPD; + ew32(CTRL, reg); + + ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_SPD_BYPS); + udelay(20); + ew32(CTRL, ctrl_reg); + ew32(CTRL_EXT, ctrl_ext); + udelay(20); + +out: + return ret_val; +} + +/** + * e1000_oem_bits_config_ich8lan - SW-based LCD Configuration + * @hw: pointer to the HW structure + * @d0_state: boolean if entering d0 or d3 device state + * + * SW will configure Gbe Disable and LPLU based on the NVM. The four bits are + * collectively called OEM bits. The OEM Write Enable bit and SW Config bit + * in NVM determines whether HW should configure LPLU and Gbe Disable. + **/ +static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state) +{ + s32 ret_val = 0; + u32 mac_reg; + u16 oem_reg; + + if (hw->mac.type != e1000_pchlan) + return ret_val; + + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) + return ret_val; + + mac_reg = er32(EXTCNF_CTRL); + if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) + goto out; + + mac_reg = er32(FEXTNVM); + if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M)) + goto out; + + mac_reg = er32(PHY_CTRL); + + ret_val = hw->phy.ops.read_phy_reg_locked(hw, HV_OEM_BITS, &oem_reg); + if (ret_val) + goto out; + + oem_reg &= ~(HV_OEM_BITS_GBE_DIS | HV_OEM_BITS_LPLU); + + if (d0_state) { + if (mac_reg & E1000_PHY_CTRL_GBE_DISABLE) + oem_reg |= HV_OEM_BITS_GBE_DIS; + + if (mac_reg & E1000_PHY_CTRL_D0A_LPLU) + oem_reg |= HV_OEM_BITS_LPLU; + } else { + if (mac_reg & E1000_PHY_CTRL_NOND0A_GBE_DISABLE) + oem_reg |= HV_OEM_BITS_GBE_DIS; + + if (mac_reg & E1000_PHY_CTRL_NOND0A_LPLU) + oem_reg |= HV_OEM_BITS_LPLU; + } + /* Restart auto-neg to activate the bits */ + oem_reg |= HV_OEM_BITS_RESTART_AN; + ret_val = hw->phy.ops.write_phy_reg_locked(hw, HV_OEM_BITS, oem_reg); + +out: + hw->phy.ops.release_phy(hw); + + return ret_val; +} + + +/** * e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be * done after every PHY reset. **/ @@ -791,10 +1168,20 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) ret_val = hw->phy.ops.acquire_phy(hw); if (ret_val) return ret_val; + hw->phy.addr = 1; - e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); + ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); + if (ret_val) + goto out; hw->phy.ops.release_phy(hw); + /* + * Configure the K1 Si workaround during phy reset assuming there is + * link so that it disables K1 if link is in 1Gbps. + */ + ret_val = e1000_k1_gig_workaround_hv(hw, true); + +out: return ret_val; } @@ -840,11 +1227,8 @@ static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw) **/ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) { - struct e1000_phy_info *phy = &hw->phy; - u32 i; - u32 data, cnf_size, cnf_base_addr, sw_cfg_mask; - s32 ret_val; - u16 word_addr, reg_data, reg_addr, phy_page = 0; + s32 ret_val = 0; + u16 reg; ret_val = e1000e_phy_hw_reset_generic(hw); if (ret_val) @@ -859,81 +1243,20 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) return ret_val; } - /* - * Initialize the PHY from the NVM on ICH platforms. This - * is needed due to an issue where the NVM configuration is - * not properly autoloaded after power transitions. - * Therefore, after each PHY reset, we will load the - * configuration data out of the NVM manually. - */ - if (hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) { - struct e1000_adapter *adapter = hw->adapter; - - /* Check if SW needs configure the PHY */ - if ((adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M_AMT) || - (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M)) - sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; - else - sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG; - - data = er32(FEXTNVM); - if (!(data & sw_cfg_mask)) - return 0; - - /* Wait for basic configuration completes before proceeding */ - e1000_lan_init_done_ich8lan(hw); - - /* - * Make sure HW does not configure LCD from PHY - * extended configuration before SW configuration - */ - data = er32(EXTCNF_CTRL); - if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) - return 0; - - cnf_size = er32(EXTCNF_SIZE); - cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK; - cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT; - if (!cnf_size) - return 0; - - cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK; - cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; - - /* Configure LCD from extended configuration region. */ - - /* cnf_base_addr is in DWORD */ - word_addr = (u16)(cnf_base_addr << 1); - - for (i = 0; i < cnf_size; i++) { - ret_val = e1000_read_nvm(hw, - (word_addr + i * 2), - 1, - ®_data); - if (ret_val) - return ret_val; - - ret_val = e1000_read_nvm(hw, - (word_addr + i * 2 + 1), - 1, - ®_addr); - if (ret_val) - return ret_val; - - /* Save off the PHY page for future writes. */ - if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) { - phy_page = reg_data; - continue; - } + /* Dummy read to clear the phy wakeup bit after lcd reset */ + if (hw->mac.type == e1000_pchlan) + e1e_rphy(hw, BM_WUC, ®); - reg_addr |= phy_page; + /* Configure the LCD with the extended configuration region in NVM */ + ret_val = e1000_sw_lcd_config_ich8lan(hw); + if (ret_val) + goto out; - ret_val = e1e_wphy(hw, (u32)reg_addr, reg_data); - if (ret_val) - return ret_val; - } - } + /* Configure the LCD with the OEM bits in NVM */ + if (hw->mac.type == e1000_pchlan) + ret_val = e1000_oem_bits_config_ich8lan(hw, true); +out: return 0; } @@ -1054,6 +1377,38 @@ static s32 e1000_check_polarity_ife_ich8lan(struct e1000_hw *hw) } /** + * e1000_set_lplu_state_pchlan - Set Low Power Link Up state + * @hw: pointer to the HW structure + * @active: true to enable LPLU, false to disable + * + * Sets the LPLU state according to the active flag. For PCH, if OEM write + * bit are disabled in the NVM, writing the LPLU bits in the MAC will not set + * the phy speed. This function will manually set the LPLU bit and restart + * auto-neg as hw would do. D3 and D0 LPLU will call the same function + * since it configures the same bit. + **/ +static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active) +{ + s32 ret_val = 0; + u16 oem_reg; + + ret_val = e1e_rphy(hw, HV_OEM_BITS, &oem_reg); + if (ret_val) + goto out; + + if (active) + oem_reg |= HV_OEM_BITS_LPLU; + else + oem_reg &= ~HV_OEM_BITS_LPLU; + + oem_reg |= HV_OEM_BITS_RESTART_AN; + ret_val = e1e_wphy(hw, HV_OEM_BITS, oem_reg); + +out: + return ret_val; +} + +/** * e1000_set_d0_lplu_state_ich8lan - Set Low Power Linkup D0 state * @hw: pointer to the HW structure * @active: TRUE to enable LPLU, FALSE to disable @@ -1314,12 +1669,11 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || (words == 0)) { hw_dbg(hw, "nvm parameter(s) out of bounds\n"); - return -E1000_ERR_NVM; + ret_val = -E1000_ERR_NVM; + goto out; } - ret_val = e1000_acquire_swflag_ich8lan(hw); - if (ret_val) - goto out; + nvm->ops.acquire_nvm(hw); ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); if (ret_val) { @@ -1345,7 +1699,7 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, } } - e1000_release_swflag_ich8lan(hw); + nvm->ops.release_nvm(hw); out: if (ret_val) @@ -1603,11 +1957,15 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, return -E1000_ERR_NVM; } + nvm->ops.acquire_nvm(hw); + for (i = 0; i < words; i++) { dev_spec->shadow_ram[offset+i].modified = 1; dev_spec->shadow_ram[offset+i].value = data[i]; } + nvm->ops.release_nvm(hw); + return 0; } @@ -1637,9 +1995,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) if (nvm->type != e1000_nvm_flash_sw) goto out; - ret_val = e1000_acquire_swflag_ich8lan(hw); - if (ret_val) - goto out; + nvm->ops.acquire_nvm(hw); /* * We're writing to the opposite bank so if we're on bank 1, @@ -1657,7 +2013,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) old_bank_offset = 0; ret_val = e1000_erase_flash_bank_ich8lan(hw, 1); if (ret_val) { - e1000_release_swflag_ich8lan(hw); + nvm->ops.release_nvm(hw); goto out; } } else { @@ -1665,7 +2021,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) new_bank_offset = 0; ret_val = e1000_erase_flash_bank_ich8lan(hw, 0); if (ret_val) { - e1000_release_swflag_ich8lan(hw); + nvm->ops.release_nvm(hw); goto out; } } @@ -1723,7 +2079,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) if (ret_val) { /* Possibly read-only, see e1000e_write_protect_nvm_ich8lan() */ hw_dbg(hw, "Flash commit failed.\n"); - e1000_release_swflag_ich8lan(hw); + nvm->ops.release_nvm(hw); goto out; } @@ -1736,7 +2092,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD; ret_val = e1000_read_flash_word_ich8lan(hw, act_offset, &data); if (ret_val) { - e1000_release_swflag_ich8lan(hw); + nvm->ops.release_nvm(hw); goto out; } data &= 0xBFFF; @@ -1744,7 +2100,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) act_offset * 2 + 1, (u8)(data >> 8)); if (ret_val) { - e1000_release_swflag_ich8lan(hw); + nvm->ops.release_nvm(hw); goto out; } @@ -1757,7 +2113,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1; ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset, 0); if (ret_val) { - e1000_release_swflag_ich8lan(hw); + nvm->ops.release_nvm(hw); goto out; } @@ -1767,7 +2123,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) dev_spec->shadow_ram[i].value = 0xFFFF; } - e1000_release_swflag_ich8lan(hw); + nvm->ops.release_nvm(hw); /* * Reload the EEPROM, or else modifications will not appear @@ -1831,14 +2187,12 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw) **/ void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw) { + struct e1000_nvm_info *nvm = &hw->nvm; union ich8_flash_protected_range pr0; union ich8_hws_flash_status hsfsts; u32 gfpreg; - s32 ret_val; - ret_val = e1000_acquire_swflag_ich8lan(hw); - if (ret_val) - return; + nvm->ops.acquire_nvm(hw); gfpreg = er32flash(ICH_FLASH_GFPREG); @@ -1859,7 +2213,7 @@ void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw) hsfsts.hsf_status.flockdn = true; ew32flash(ICH_FLASH_HSFSTS, hsfsts.regval); - e1000_release_swflag_ich8lan(hw); + nvm->ops.release_nvm(hw); } /** @@ -2229,6 +2583,8 @@ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw) **/ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) { + struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; + u16 reg; u32 ctrl, icr, kab; s32 ret_val; @@ -2263,6 +2619,18 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) ew32(PBS, E1000_PBS_16K); } + if (hw->mac.type == e1000_pchlan) { + /* Save the NVM K1 bit setting*/ + ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, ®); + if (ret_val) + return ret_val; + + if (reg & E1000_NVM_K1_ENABLE) + dev_spec->nvm_k1_enabled = true; + else + dev_spec->nvm_k1_enabled = false; + } + ctrl = er32(CTRL); if (!e1000_check_reset_block(hw)) { @@ -2304,7 +2672,19 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) hw_dbg(hw, "Auto Read Done did not complete\n"); } } + /* Dummy read to clear the phy wakeup bit after lcd reset */ + if (hw->mac.type == e1000_pchlan) + e1e_rphy(hw, BM_WUC, ®); + ret_val = e1000_sw_lcd_config_ich8lan(hw); + if (ret_val) + goto out; + + if (hw->mac.type == e1000_pchlan) { + ret_val = e1000_oem_bits_config_ich8lan(hw, true); + if (ret_val) + goto out; + } /* * For PCH, this write will make sure that any noise * will be detected as a CRC error and be dropped rather than show up @@ -2323,6 +2703,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) if (hw->mac.type == e1000_pchlan) ret_val = e1000_hv_phy_workarounds_ich8lan(hw); +out: return ret_val; } @@ -2627,14 +3008,6 @@ static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, if (ret_val) return ret_val; - if ((hw->mac.type == e1000_pchlan) && (*speed == SPEED_1000)) { - ret_val = e1000e_write_kmrn_reg(hw, - E1000_KMRNCTRLSTA_K1_CONFIG, - E1000_KMRNCTRLSTA_K1_DISABLE); - if (ret_val) - return ret_val; - } - if ((hw->mac.type == e1000_ich8lan) && (hw->phy.type == e1000_phy_igp_3) && (*speed == SPEED_1000)) { @@ -2843,9 +3216,8 @@ void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw) E1000_PHY_CTRL_GBE_DISABLE; ew32(PHY_CTRL, phy_ctrl); - /* Workaround SWFLAG unexpectedly set during S0->Sx */ if (hw->mac.type == e1000_pchlan) - udelay(500); + e1000_phy_hw_reset_ich8lan(hw); default: break; } @@ -3113,9 +3485,9 @@ static struct e1000_phy_operations ich8_phy_ops = { }; static struct e1000_nvm_operations ich8_nvm_ops = { - .acquire_nvm = e1000_acquire_swflag_ich8lan, + .acquire_nvm = e1000_acquire_nvm_ich8lan, .read_nvm = e1000_read_nvm_ich8lan, - .release_nvm = e1000_release_swflag_ich8lan, + .release_nvm = e1000_release_nvm_ich8lan, .update_nvm = e1000_update_nvm_checksum_ich8lan, .valid_led_default = e1000_valid_led_default_ich8lan, .validate_nvm = e1000_validate_nvm_checksum_ich8lan, diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index 994401fd0664..03175b3a2c9e 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -95,13 +95,6 @@ static const u16 e1000_igp_2_cable_length_table[] = /* BM PHY Copper Specific Control 1 */ #define BM_CS_CTRL1 16 -/* BM PHY Copper Specific Status */ -#define BM_CS_STATUS 17 -#define BM_CS_STATUS_LINK_UP 0x0400 -#define BM_CS_STATUS_RESOLVED 0x0800 -#define BM_CS_STATUS_SPEED_MASK 0xC000 -#define BM_CS_STATUS_SPEED_1000 0x8000 - #define HV_MUX_DATA_CTRL PHY_REG(776, 16) #define HV_MUX_DATA_CTRL_GEN_TO_MAC 0x0400 #define HV_MUX_DATA_CTRL_FORCE_SPEED 0x0004 @@ -164,16 +157,25 @@ s32 e1000e_get_phy_id(struct e1000_hw *hw) * MDIC mode. No harm in trying again in this case since * the PHY ID is unknown at this point anyway */ + ret_val = phy->ops.acquire_phy(hw); + if (ret_val) + goto out; ret_val = e1000_set_mdio_slow_mode_hv(hw, true); if (ret_val) goto out; + phy->ops.release_phy(hw); retry_count++; } out: /* Revert to MDIO fast mode, if applicable */ - if (retry_count) + if (retry_count) { + ret_val = phy->ops.acquire_phy(hw); + if (ret_val) + return ret_val; ret_val = e1000_set_mdio_slow_mode_hv(hw, false); + phy->ops.release_phy(hw); + } return ret_val; } @@ -354,94 +356,173 @@ s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data) } /** - * e1000e_read_phy_reg_igp - Read igp PHY register + * __e1000e_read_phy_reg_igp - Read igp PHY register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data + * @locked: semaphore has already been acquired or not * * Acquires semaphore, if necessary, then reads the PHY register at offset - * and storing the retrieved information in data. Release any acquired + * and stores the retrieved information in data. Release any acquired * semaphores before exiting. **/ -s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) +static s32 __e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data, + bool locked) { - s32 ret_val; + s32 ret_val = 0; - ret_val = hw->phy.ops.acquire_phy(hw); - if (ret_val) - return ret_val; + if (!locked) { + if (!(hw->phy.ops.acquire_phy)) + goto out; + + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) + goto out; + } if (offset > MAX_PHY_MULTI_PAGE_REG) { ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, (u16)offset); - if (ret_val) { - hw->phy.ops.release_phy(hw); - return ret_val; - } + if (ret_val) + goto release; } ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - - hw->phy.ops.release_phy(hw); + data); +release: + if (!locked) + hw->phy.ops.release_phy(hw); +out: return ret_val; } /** + * e1000e_read_phy_reg_igp - Read igp PHY register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data + * + * Acquires semaphore then reads the PHY register at offset and stores the + * retrieved information in data. + * Release the acquired semaphore before exiting. + **/ +s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) +{ + return __e1000e_read_phy_reg_igp(hw, offset, data, false); +} + +/** + * e1000e_read_phy_reg_igp_locked - Read igp PHY register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data + * + * Reads the PHY register at offset and stores the retrieved information + * in data. Assumes semaphore already acquired. + **/ +s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data) +{ + return __e1000e_read_phy_reg_igp(hw, offset, data, true); +} + +/** * e1000e_write_phy_reg_igp - Write igp PHY register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset + * @locked: semaphore has already been acquired or not * * Acquires semaphore, if necessary, then writes the data to PHY register * at the offset. Release any acquired semaphores before exiting. **/ -s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) +static s32 __e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data, + bool locked) { - s32 ret_val; + s32 ret_val = 0; - ret_val = hw->phy.ops.acquire_phy(hw); - if (ret_val) - return ret_val; + if (!locked) { + if (!(hw->phy.ops.acquire_phy)) + goto out; + + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) + goto out; + } if (offset > MAX_PHY_MULTI_PAGE_REG) { ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, (u16)offset); - if (ret_val) { - hw->phy.ops.release_phy(hw); - return ret_val; - } + if (ret_val) + goto release; } ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); - hw->phy.ops.release_phy(hw); +release: + if (!locked) + hw->phy.ops.release_phy(hw); +out: return ret_val; } /** - * e1000e_read_kmrn_reg - Read kumeran register + * e1000e_write_phy_reg_igp - Write igp PHY register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset + * + * Acquires semaphore then writes the data to PHY register + * at the offset. Release any acquired semaphores before exiting. + **/ +s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) +{ + return __e1000e_write_phy_reg_igp(hw, offset, data, false); +} + +/** + * e1000e_write_phy_reg_igp_locked - Write igp PHY register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset + * + * Writes the data to PHY register at the offset. + * Assumes semaphore already acquired. + **/ +s32 e1000e_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data) +{ + return __e1000e_write_phy_reg_igp(hw, offset, data, true); +} + +/** + * __e1000_read_kmrn_reg - Read kumeran register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data + * @locked: semaphore has already been acquired or not * * Acquires semaphore, if necessary. Then reads the PHY register at offset * using the kumeran interface. The information retrieved is stored in data. * Release any acquired semaphores before exiting. **/ -s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data) +static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data, + bool locked) { u32 kmrnctrlsta; - s32 ret_val; + s32 ret_val = 0; - ret_val = hw->phy.ops.acquire_phy(hw); - if (ret_val) - return ret_val; + if (!locked) { + if (!(hw->phy.ops.acquire_phy)) + goto out; + + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) + goto out; + } kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; @@ -452,41 +533,111 @@ s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data) kmrnctrlsta = er32(KMRNCTRLSTA); *data = (u16)kmrnctrlsta; - hw->phy.ops.release_phy(hw); + if (!locked) + hw->phy.ops.release_phy(hw); +out: return ret_val; } /** - * e1000e_write_kmrn_reg - Write kumeran register + * e1000e_read_kmrn_reg - Read kumeran register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data + * + * Acquires semaphore then reads the PHY register at offset using the + * kumeran interface. The information retrieved is stored in data. + * Release the acquired semaphore before exiting. + **/ +s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data) +{ + return __e1000_read_kmrn_reg(hw, offset, data, false); +} + +/** + * e1000e_read_kmrn_reg_locked - Read kumeran register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data + * + * Reads the PHY register at offset using the kumeran interface. The + * information retrieved is stored in data. + * Assumes semaphore already acquired. + **/ +s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data) +{ + return __e1000_read_kmrn_reg(hw, offset, data, true); +} + +/** + * __e1000_write_kmrn_reg - Write kumeran register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset + * @locked: semaphore has already been acquired or not * * Acquires semaphore, if necessary. Then write the data to PHY register * at the offset using the kumeran interface. Release any acquired semaphores * before exiting. **/ -s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data) +static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data, + bool locked) { u32 kmrnctrlsta; - s32 ret_val; + s32 ret_val = 0; - ret_val = hw->phy.ops.acquire_phy(hw); - if (ret_val) - return ret_val; + if (!locked) { + if (!(hw->phy.ops.acquire_phy)) + goto out; + + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) + goto out; + } kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & E1000_KMRNCTRLSTA_OFFSET) | data; ew32(KMRNCTRLSTA, kmrnctrlsta); udelay(2); - hw->phy.ops.release_phy(hw); + if (!locked) + hw->phy.ops.release_phy(hw); + +out: return ret_val; } /** + * e1000e_write_kmrn_reg - Write kumeran register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset + * + * Acquires semaphore then writes the data to the PHY register at the offset + * using the kumeran interface. Release the acquired semaphore before exiting. + **/ +s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data) +{ + return __e1000_write_kmrn_reg(hw, offset, data, false); +} + +/** + * e1000e_write_kmrn_reg_locked - Write kumeran register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset + * + * Write the data to PHY register at the offset using the kumeran interface. + * Assumes semaphore already acquired. + **/ +s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data) +{ + return __e1000_write_kmrn_reg(hw, offset, data, true); +} + +/** * e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link * @hw: pointer to the HW structure * @@ -2105,6 +2256,10 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) u32 page = offset >> IGP_PAGE_SHIFT; u32 page_shift = 0; + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) + return ret_val; + /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, @@ -2112,10 +2267,6 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) goto out; } - ret_val = hw->phy.ops.acquire_phy(hw); - if (ret_val) - goto out; - hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset); if (offset > MAX_PHY_MULTI_PAGE_REG) { @@ -2135,18 +2286,15 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) /* Page is shifted left, PHY expects (page x 32) */ ret_val = e1000e_write_phy_reg_mdic(hw, page_select, (page << page_shift)); - if (ret_val) { - hw->phy.ops.release_phy(hw); + if (ret_val) goto out; - } } ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); - hw->phy.ops.release_phy(hw); - out: + hw->phy.ops.release_phy(hw); return ret_val; } @@ -2167,6 +2315,10 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) u32 page = offset >> IGP_PAGE_SHIFT; u32 page_shift = 0; + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) + return ret_val; + /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, @@ -2174,10 +2326,6 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) goto out; } - ret_val = hw->phy.ops.acquire_phy(hw); - if (ret_val) - goto out; - hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset); if (offset > MAX_PHY_MULTI_PAGE_REG) { @@ -2197,17 +2345,14 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) /* Page is shifted left, PHY expects (page x 32) */ ret_val = e1000e_write_phy_reg_mdic(hw, page_select, (page << page_shift)); - if (ret_val) { - hw->phy.ops.release_phy(hw); + if (ret_val) goto out; - } } ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); - hw->phy.ops.release_phy(hw); - out: + hw->phy.ops.release_phy(hw); return ret_val; } @@ -2226,17 +2371,17 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data) s32 ret_val; u16 page = (u16)(offset >> IGP_PAGE_SHIFT); + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) + return ret_val; + /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, true); - return ret_val; + goto out; } - ret_val = hw->phy.ops.acquire_phy(hw); - if (ret_val) - return ret_val; - hw->phy.addr = 1; if (offset > MAX_PHY_MULTI_PAGE_REG) { @@ -2245,16 +2390,14 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data) ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, page); - if (ret_val) { - hw->phy.ops.release_phy(hw); - return ret_val; - } + if (ret_val) + goto out; } ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); +out: hw->phy.ops.release_phy(hw); - return ret_val; } @@ -2272,17 +2415,17 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data) s32 ret_val; u16 page = (u16)(offset >> IGP_PAGE_SHIFT); + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) + return ret_val; + /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, false); - return ret_val; + goto out; } - ret_val = hw->phy.ops.acquire_phy(hw); - if (ret_val) - return ret_val; - hw->phy.addr = 1; if (offset > MAX_PHY_MULTI_PAGE_REG) { @@ -2290,17 +2433,15 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data) ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, page); - if (ret_val) { - hw->phy.ops.release_phy(hw); - return ret_val; - } + if (ret_val) + goto out; } ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); +out: hw->phy.ops.release_phy(hw); - return ret_val; } @@ -2320,6 +2461,8 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data) * 3) Write the address using the address opcode (0x11) * 4) Read or write the data using the data opcode (0x12) * 5) Restore 769_17.2 to its original value + * + * Assumes semaphore already acquired. **/ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data, bool read) @@ -2327,20 +2470,12 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, s32 ret_val; u16 reg = BM_PHY_REG_NUM(offset); u16 phy_reg = 0; - u8 phy_acquired = 1; - /* Gig must be disabled for MDIO accesses to page 800 */ if ((hw->mac.type == e1000_pchlan) && (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE))) hw_dbg(hw, "Attempting to access page 800 while gig enabled\n"); - ret_val = hw->phy.ops.acquire_phy(hw); - if (ret_val) { - phy_acquired = 0; - goto out; - } - /* All operations in this function are phy address 1 */ hw->phy.addr = 1; @@ -2397,8 +2532,6 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); out: - if (phy_acquired == 1) - hw->phy.ops.release_phy(hw); return ret_val; } @@ -2439,52 +2572,63 @@ static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active) return 0; } +/** + * e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode + * @hw: pointer to the HW structure + * @slow: true for slow mode, false for normal mode + * + * Assumes semaphore already acquired. + **/ s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow) { s32 ret_val = 0; u16 data = 0; - ret_val = hw->phy.ops.acquire_phy(hw); - if (ret_val) - return ret_val; - /* Set MDIO mode - page 769, register 16: 0x2580==slow, 0x2180==fast */ hw->phy.addr = 1; ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT)); - if (ret_val) { - hw->phy.ops.release_phy(hw); - return ret_val; - } + if (ret_val) + goto out; + ret_val = e1000e_write_phy_reg_mdic(hw, BM_CS_CTRL1, (0x2180 | (slow << 10))); + if (ret_val) + goto out; /* dummy read when reverting to fast mode - throw away result */ if (!slow) - e1000e_read_phy_reg_mdic(hw, BM_CS_CTRL1, &data); - - hw->phy.ops.release_phy(hw); + ret_val = e1000e_read_phy_reg_mdic(hw, BM_CS_CTRL1, &data); +out: return ret_val; } /** - * e1000_read_phy_reg_hv - Read HV PHY register + * __e1000_read_phy_reg_hv - Read HV PHY register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data + * @locked: semaphore has already been acquired or not * * Acquires semaphore, if necessary, then reads the PHY register at offset - * and storing the retrieved information in data. Release any acquired + * and stores the retrieved information in data. Release any acquired * semaphore before exiting. **/ -s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data) +static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, + bool locked) { s32 ret_val; u16 page = BM_PHY_REG_PAGE(offset); u16 reg = BM_PHY_REG_NUM(offset); bool in_slow_mode = false; + if (!locked) { + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) + return ret_val; + } + /* Workaround failure in MDIO access while cable is disconnected */ if ((hw->phy.type == e1000_phy_82577) && !(er32(STATUS) & E1000_STATUS_LU)) { @@ -2508,10 +2652,6 @@ s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data) goto out; } - ret_val = hw->phy.ops.acquire_phy(hw); - if (ret_val) - goto out; - hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); if (page == HV_INTC_FC_PAGE_START) @@ -2529,42 +2669,76 @@ s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data) ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, (page << IGP_PAGE_SHIFT)); - if (ret_val) { - hw->phy.ops.release_phy(hw); - goto out; - } hw->phy.addr = phy_addr; } } ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, data); - hw->phy.ops.release_phy(hw); - out: /* Revert to MDIO fast mode, if applicable */ if ((hw->phy.type == e1000_phy_82577) && in_slow_mode) ret_val = e1000_set_mdio_slow_mode_hv(hw, false); + if (!locked) + hw->phy.ops.release_phy(hw); + return ret_val; } /** - * e1000_write_phy_reg_hv - Write HV PHY register + * e1000_read_phy_reg_hv - Read HV PHY register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data + * + * Acquires semaphore then reads the PHY register at offset and stores + * the retrieved information in data. Release the acquired semaphore + * before exiting. + **/ +s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data) +{ + return __e1000_read_phy_reg_hv(hw, offset, data, false); +} + +/** + * e1000_read_phy_reg_hv_locked - Read HV PHY register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data + * + * Reads the PHY register at offset and stores the retrieved information + * in data. Assumes semaphore already acquired. + **/ +s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data) +{ + return __e1000_read_phy_reg_hv(hw, offset, data, true); +} + +/** + * __e1000_write_phy_reg_hv - Write HV PHY register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset + * @locked: semaphore has already been acquired or not * * Acquires semaphore, if necessary, then writes the data to PHY register * at the offset. Release any acquired semaphores before exiting. **/ -s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data) +static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, + bool locked) { s32 ret_val; u16 page = BM_PHY_REG_PAGE(offset); u16 reg = BM_PHY_REG_NUM(offset); bool in_slow_mode = false; + if (!locked) { + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) + return ret_val; + } + /* Workaround failure in MDIO access while cable is disconnected */ if ((hw->phy.type == e1000_phy_82577) && !(er32(STATUS) & E1000_STATUS_LU)) { @@ -2588,10 +2762,6 @@ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data) goto out; } - ret_val = hw->phy.ops.acquire_phy(hw); - if (ret_val) - goto out; - hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); if (page == HV_INTC_FC_PAGE_START) @@ -2607,15 +2777,10 @@ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data) ((MAX_PHY_REG_ADDRESS & reg) == 0) && (data & (1 << 11))) { u16 data2 = 0x7EFF; - hw->phy.ops.release_phy(hw); ret_val = e1000_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3, &data2, false); if (ret_val) goto out; - - ret_val = hw->phy.ops.acquire_phy(hw); - if (ret_val) - goto out; } if (reg > MAX_PHY_MULTI_PAGE_REG) { @@ -2630,27 +2795,53 @@ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data) ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, (page << IGP_PAGE_SHIFT)); - if (ret_val) { - hw->phy.ops.release_phy(hw); - goto out; - } hw->phy.addr = phy_addr; } } ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, data); - hw->phy.ops.release_phy(hw); out: /* Revert to MDIO fast mode, if applicable */ if ((hw->phy.type == e1000_phy_82577) && in_slow_mode) ret_val = e1000_set_mdio_slow_mode_hv(hw, false); + if (!locked) + hw->phy.ops.release_phy(hw); + return ret_val; } /** + * e1000_write_phy_reg_hv - Write HV PHY register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset + * + * Acquires semaphore then writes the data to PHY register at the offset. + * Release the acquired semaphores before exiting. + **/ +s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data) +{ + return __e1000_write_phy_reg_hv(hw, offset, data, false); +} + +/** + * e1000_write_phy_reg_hv_locked - Write HV PHY register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset + * + * Writes the data to PHY register at the offset. Assumes semaphore + * already acquired. + **/ +s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data) +{ + return __e1000_write_phy_reg_hv(hw, offset, data, true); +} + +/** * e1000_get_phy_addr_for_hv_page - Get PHY adrress based on page * @page: page to be accessed **/ @@ -2671,10 +2862,9 @@ static u32 e1000_get_phy_addr_for_hv_page(u32 page) * @data: pointer to the data to be read or written * @read: determines if operation is read or written * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and storing the retreived information in data. Release any acquired - * semaphores before exiting. Note that the procedure to read these regs - * uses the address port and data port to read/write. + * Reads the PHY register at offset and stores the retreived information + * in data. Assumes semaphore already acquired. Note that the procedure + * to read these regs uses the address port and data port to read/write. **/ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, u16 *data, bool read) @@ -2682,20 +2872,12 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, s32 ret_val; u32 addr_reg = 0; u32 data_reg = 0; - u8 phy_acquired = 1; /* This takes care of the difference with desktop vs mobile phy */ addr_reg = (hw->phy.type == e1000_phy_82578) ? I82578_ADDR_REG : I82577_ADDR_REG; data_reg = addr_reg + 1; - ret_val = hw->phy.ops.acquire_phy(hw); - if (ret_val) { - hw_dbg(hw, "Could not acquire PHY\n"); - phy_acquired = 0; - goto out; - } - /* All operations in this function are phy address 2 */ hw->phy.addr = 2; @@ -2718,8 +2900,6 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, } out: - if (phy_acquired == 1) - hw->phy.ops.release_phy(hw); return ret_val; } diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c index 801f088c134f..030913f8bd26 100644 --- a/drivers/net/ifb.c +++ b/drivers/net/ifb.c @@ -98,12 +98,13 @@ static void ri_tasklet(unsigned long dev) stats->tx_packets++; stats->tx_bytes +=skb->len; - skb->dev = __dev_get_by_index(&init_net, skb->iif); + skb->dev = dev_get_by_index(&init_net, skb->iif); if (!skb->dev) { dev_kfree_skb(skb); stats->tx_dropped++; break; } + dev_put(skb->dev); skb->iif = _dev->ifindex; if (from & AT_EGRESS) { diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index deaea8fa1032..b243ed3b0c36 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -732,7 +732,7 @@ static int igb_set_ringparam(struct net_device *netdev, { struct igb_adapter *adapter = netdev_priv(netdev); struct igb_ring *temp_ring; - int i, err; + int i, err = 0; u32 new_rx_count, new_tx_count; if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) @@ -752,18 +752,30 @@ static int igb_set_ringparam(struct net_device *netdev, return 0; } + while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) + msleep(1); + + if (!netif_running(adapter->netdev)) { + for (i = 0; i < adapter->num_tx_queues; i++) + adapter->tx_ring[i].count = new_tx_count; + for (i = 0; i < adapter->num_rx_queues; i++) + adapter->rx_ring[i].count = new_rx_count; + adapter->tx_ring_count = new_tx_count; + adapter->rx_ring_count = new_rx_count; + goto clear_reset; + } + if (adapter->num_tx_queues > adapter->num_rx_queues) temp_ring = vmalloc(adapter->num_tx_queues * sizeof(struct igb_ring)); else temp_ring = vmalloc(adapter->num_rx_queues * sizeof(struct igb_ring)); - if (!temp_ring) - return -ENOMEM; - while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) - msleep(1); + if (!temp_ring) { + err = -ENOMEM; + goto clear_reset; + } - if (netif_running(adapter->netdev)) - igb_down(adapter); + igb_down(adapter); /* * We can't just free everything and then setup again, @@ -820,14 +832,11 @@ static int igb_set_ringparam(struct net_device *netdev, adapter->rx_ring_count = new_rx_count; } - - err = 0; err_setup: - if (netif_running(adapter->netdev)) - igb_up(adapter); - - clear_bit(__IGB_RESETTING, &adapter->state); + igb_up(adapter); vfree(temp_ring); +clear_reset: + clear_bit(__IGB_RESETTING, &adapter->state); return err; } diff --git a/drivers/net/igbvf/ethtool.c b/drivers/net/igbvf/ethtool.c index ee17a097d1ca..c68265bd0d1a 100644 --- a/drivers/net/igbvf/ethtool.c +++ b/drivers/net/igbvf/ethtool.c @@ -279,7 +279,7 @@ static int igbvf_set_ringparam(struct net_device *netdev, { struct igbvf_adapter *adapter = netdev_priv(netdev); struct igbvf_ring *temp_ring; - int err; + int err = 0; u32 new_rx_count, new_tx_count; if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) @@ -299,15 +299,22 @@ static int igbvf_set_ringparam(struct net_device *netdev, return 0; } - temp_ring = vmalloc(sizeof(struct igbvf_ring)); - if (!temp_ring) - return -ENOMEM; - while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state)) msleep(1); - if (netif_running(adapter->netdev)) - igbvf_down(adapter); + if (!netif_running(adapter->netdev)) { + adapter->tx_ring->count = new_tx_count; + adapter->rx_ring->count = new_rx_count; + goto clear_reset; + } + + temp_ring = vmalloc(sizeof(struct igbvf_ring)); + if (!temp_ring) { + err = -ENOMEM; + goto clear_reset; + } + + igbvf_down(adapter); /* * We can't just free everything and then setup again, @@ -339,14 +346,11 @@ static int igbvf_set_ringparam(struct net_device *netdev, memcpy(adapter->rx_ring, temp_ring,sizeof(struct igbvf_ring)); } - - err = 0; err_setup: - if (netif_running(adapter->netdev)) - igbvf_up(adapter); - - clear_bit(__IGBVF_RESETTING, &adapter->state); + igbvf_up(adapter); vfree(temp_ring); +clear_reset: + clear_bit(__IGBVF_RESETTING, &adapter->state); return err; } diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index fa314cb005a4..856c18c207f3 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -798,7 +798,7 @@ static int ixgbe_set_ringparam(struct net_device *netdev, { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_ring *temp_tx_ring, *temp_rx_ring; - int i, err; + int i, err = 0; u32 new_rx_count, new_tx_count; bool need_update = false; @@ -822,6 +822,16 @@ static int ixgbe_set_ringparam(struct net_device *netdev, while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) msleep(1); + if (!netif_running(adapter->netdev)) { + for (i = 0; i < adapter->num_tx_queues; i++) + adapter->tx_ring[i].count = new_tx_count; + for (i = 0; i < adapter->num_rx_queues; i++) + adapter->rx_ring[i].count = new_rx_count; + adapter->tx_ring_count = new_tx_count; + adapter->rx_ring_count = new_rx_count; + goto err_setup; + } + temp_tx_ring = kcalloc(adapter->num_tx_queues, sizeof(struct ixgbe_ring), GFP_KERNEL); if (!temp_tx_ring) { @@ -879,8 +889,7 @@ static int ixgbe_set_ringparam(struct net_device *netdev, /* if rings need to be updated, here's the place to do it in one shot */ if (need_update) { - if (netif_running(netdev)) - ixgbe_down(adapter); + ixgbe_down(adapter); /* tx */ if (new_tx_count != adapter->tx_ring_count) { @@ -897,13 +906,8 @@ static int ixgbe_set_ringparam(struct net_device *netdev, temp_rx_ring = NULL; adapter->rx_ring_count = new_rx_count; } - } - - /* success! */ - err = 0; - if (netif_running(netdev)) ixgbe_up(adapter); - + } err_setup: clear_bit(__IXGBE_RESETTING, &adapter->state); return err; diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c index 5dd7225b178e..291a505fd4fc 100644 --- a/drivers/net/mlx4/main.c +++ b/drivers/net/mlx4/main.c @@ -1282,6 +1282,7 @@ static struct pci_device_id mlx4_pci_table[] = { { PCI_VDEVICE(MELLANOX, 0x6372) }, /* MT25458 ConnectX EN 10GBASE-T 10GigE */ { PCI_VDEVICE(MELLANOX, 0x675a) }, /* MT25458 ConnectX EN 10GBASE-T+Gen2 10GigE */ { PCI_VDEVICE(MELLANOX, 0x6764) }, /* MT26468 ConnectX EN 10GigE PCIe gen2*/ + { PCI_VDEVICE(MELLANOX, 0x6746) }, /* MT26438 ConnectX EN 40GigE PCIe gen2 5GT/s */ { PCI_VDEVICE(MELLANOX, 0x676e) }, /* MT26478 ConnectX2 40GigE PCIe gen2 */ { 0, } }; diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 6930c87f362e..f3624517cb0e 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -75,7 +75,7 @@ #include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.5.0-1.432" +#define MYRI10GE_VERSION_STR "1.5.1-1.451" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); @@ -1624,10 +1624,21 @@ myri10ge_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) return 0; } } - if (*ptr == 'R' || *ptr == 'Q') { - /* We've found either an XFP or quad ribbon fiber */ + if (*ptr == '2') + ptr++; + if (*ptr == 'R' || *ptr == 'Q' || *ptr == 'S') { + /* We've found either an XFP, quad ribbon fiber, or SFP+ */ cmd->port = PORT_FIBRE; + cmd->supported |= SUPPORTED_FIBRE; + cmd->advertising |= ADVERTISED_FIBRE; + } else { + cmd->port = PORT_OTHER; } + if (*ptr == 'R' || *ptr == 'S') + cmd->transceiver = XCVR_EXTERNAL; + else + cmd->transceiver = XCVR_INTERNAL; + return 0; } diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index 7a7177421d7c..1c46da632125 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -419,6 +419,7 @@ enum { #define NETXEN_CRB_ROMUSB \ NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_ROMUSB) #define NETXEN_CRB_I2Q NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_I2Q) +#define NETXEN_CRB_I2C0 NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_I2C0) #define NETXEN_CRB_SMB NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_SMB) #define NETXEN_CRB_MAX NETXEN_PCI_CRB_WINDOW(64) diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 32314000dfcd..3185a98b0917 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -1901,22 +1901,16 @@ netxen_setup_hwops(struct netxen_adapter *adapter) int netxen_nic_get_board_info(struct netxen_adapter *adapter) { - int offset, board_type, magic, header_version; + int offset, board_type, magic; struct pci_dev *pdev = adapter->pdev; offset = NX_FW_MAGIC_OFFSET; if (netxen_rom_fast_read(adapter, offset, &magic)) return -EIO; - offset = NX_HDR_VERSION_OFFSET; - if (netxen_rom_fast_read(adapter, offset, &header_version)) - return -EIO; - - if (magic != NETXEN_BDINFO_MAGIC || - header_version != NETXEN_BDINFO_VERSION) { - dev_err(&pdev->dev, - "invalid board config, magic=%08x, version=%08x\n", - magic, header_version); + if (magic != NETXEN_BDINFO_MAGIC) { + dev_err(&pdev->dev, "invalid board config, magic=%08x\n", + magic); return -EIO; } diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 91c2bc61c8eb..e40b914d6faf 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -531,6 +531,8 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) continue; if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { + if (off == (NETXEN_CRB_I2C0 + 0x1c)) + continue; /* do not reset PCI */ if (off == (ROMUSB_GLB + 0xbc)) continue; @@ -553,12 +555,6 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) continue; } - if (off == NETXEN_ADDR_ERROR) { - printk(KERN_ERR "%s: Err: Unknown addr: 0x%08x\n", - netxen_nic_driver_name, buf[i].addr); - continue; - } - init_delay = 1; /* After writing this register, HW needs time for CRB */ /* to quiet down (else crb_window returns 0xffffffff) */ diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 7fc15e9e8adb..0b4a56a8c8d5 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -1919,6 +1919,7 @@ static void netxen_tx_timeout_task(struct work_struct *work) request_reset: adapter->need_fw_reset = 1; + clear_bit(__NX_RESETTING, &adapter->state); } struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index bd3447f04902..94c9ad2746bc 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -1760,7 +1760,7 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_DEVICE_CIS_MANF_CARD(0xc00f, 0x0002, "cis/LA-PCM.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("KTI", "PE520 PLUS", 0xad180345, 0x9d58d392, "PE520.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "cis/NE2K.cis"), - PCMCIA_DEVICE_CIS_PROD_ID12("PMX ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "PE-200.cis"), + PCMCIA_DEVICE_CIS_PROD_ID12("PMX ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "cis/PE-200.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "cis/tamarack.cis"), PCMCIA_DEVICE_PROD_ID12("Ethernet", "CF Size PC Card", 0x00b2e941, 0x43ac239b), PCMCIA_DEVICE_PROD_ID123("Fast Ethernet", "CF Size PC Card", "1.0", diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 7cbf6f9b51de..2559991eea6a 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -111,9 +111,6 @@ struct pppoe_net { rwlock_t hash_lock; }; -/* to eliminate a race btw pppoe_flush_dev and pppoe_release */ -static DEFINE_SPINLOCK(flush_lock); - /* * PPPoE could be in the following stages: * 1) Discovery stage (to obtain remote MAC and Session ID) @@ -303,45 +300,48 @@ static void pppoe_flush_dev(struct net_device *dev) write_lock_bh(&pn->hash_lock); for (i = 0; i < PPPOE_HASH_SIZE; i++) { struct pppox_sock *po = pn->hash_table[i]; + struct sock *sk; - while (po != NULL) { - struct sock *sk; - if (po->pppoe_dev != dev) { + while (po) { + while (po && po->pppoe_dev != dev) { po = po->next; - continue; } + + if (!po) + break; + sk = sk_pppox(po); - spin_lock(&flush_lock); - po->pppoe_dev = NULL; - spin_unlock(&flush_lock); - dev_put(dev); /* We always grab the socket lock, followed by the - * hash_lock, in that order. Since we should - * hold the sock lock while doing any unbinding, - * we need to release the lock we're holding. - * Hold a reference to the sock so it doesn't disappear - * as we're jumping between locks. + * hash_lock, in that order. Since we should hold the + * sock lock while doing any unbinding, we need to + * release the lock we're holding. Hold a reference to + * the sock so it doesn't disappear as we're jumping + * between locks. */ sock_hold(sk); - write_unlock_bh(&pn->hash_lock); lock_sock(sk); - if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) { + if (po->pppoe_dev == dev + && sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) { pppox_unbind_sock(sk); sk->sk_state = PPPOX_ZOMBIE; sk->sk_state_change(sk); + po->pppoe_dev = NULL; + dev_put(dev); } release_sock(sk); sock_put(sk); - /* Restart scan at the beginning of this hash chain. - * While the lock was dropped the chain contents may - * have changed. + /* Restart the process from the start of the current + * hash chain. We dropped locks so the world may have + * change from underneath us. */ + + BUG_ON(pppoe_pernet(dev_net(dev)) == NULL); write_lock_bh(&pn->hash_lock); po = pn->hash_table[i]; } @@ -388,11 +388,16 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb) struct pppox_sock *po = pppox_sk(sk); struct pppox_sock *relay_po; + /* Backlog receive. Semantics of backlog rcv preclude any code from + * executing in lock_sock()/release_sock() bounds; meaning sk->sk_state + * can't change. + */ + if (sk->sk_state & PPPOX_BOUND) { ppp_input(&po->chan, skb); } else if (sk->sk_state & PPPOX_RELAY) { - relay_po = get_item_by_addr(dev_net(po->pppoe_dev), - &po->pppoe_relay); + relay_po = get_item_by_addr(sock_net(sk), + &po->pppoe_relay); if (relay_po == NULL) goto abort_kfree; @@ -447,6 +452,10 @@ static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev, goto drop; pn = pppoe_pernet(dev_net(dev)); + + /* Note that get_item does a sock_hold(), so sk_pppox(po) + * is known to be safe. + */ po = get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex); if (!po) goto drop; @@ -561,6 +570,7 @@ static int pppoe_release(struct socket *sock) struct sock *sk = sock->sk; struct pppox_sock *po; struct pppoe_net *pn; + struct net *net = NULL; if (!sk) return 0; @@ -571,44 +581,28 @@ static int pppoe_release(struct socket *sock) return -EBADF; } + po = pppox_sk(sk); + + if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) { + dev_put(po->pppoe_dev); + po->pppoe_dev = NULL; + } + pppox_unbind_sock(sk); /* Signal the death of the socket. */ sk->sk_state = PPPOX_DEAD; - /* - * pppoe_flush_dev could lead to a race with - * this routine so we use flush_lock to eliminate - * such a case (we only need per-net specific data) - */ - spin_lock(&flush_lock); - po = pppox_sk(sk); - if (!po->pppoe_dev) { - spin_unlock(&flush_lock); - goto out; - } - pn = pppoe_pernet(dev_net(po->pppoe_dev)); - spin_unlock(&flush_lock); + net = sock_net(sk); + pn = pppoe_pernet(net); /* * protect "po" from concurrent updates * on pppoe_flush_dev */ - write_lock_bh(&pn->hash_lock); + delete_item(pn, po->pppoe_pa.sid, po->pppoe_pa.remote, + po->pppoe_ifindex); - po = pppox_sk(sk); - if (stage_session(po->pppoe_pa.sid)) - __delete_item(pn, po->pppoe_pa.sid, po->pppoe_pa.remote, - po->pppoe_ifindex); - - if (po->pppoe_dev) { - dev_put(po->pppoe_dev); - po->pppoe_dev = NULL; - } - - write_unlock_bh(&pn->hash_lock); - -out: sock_orphan(sk); sock->sk = NULL; @@ -625,8 +619,9 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, struct sock *sk = sock->sk; struct sockaddr_pppox *sp = (struct sockaddr_pppox *)uservaddr; struct pppox_sock *po = pppox_sk(sk); - struct net_device *dev; + struct net_device *dev = NULL; struct pppoe_net *pn; + struct net *net = NULL; int error; lock_sock(sk); @@ -652,12 +647,14 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, /* Delete the old binding */ if (stage_session(po->pppoe_pa.sid)) { pppox_unbind_sock(sk); + pn = pppoe_pernet(sock_net(sk)); + delete_item(pn, po->pppoe_pa.sid, + po->pppoe_pa.remote, po->pppoe_ifindex); if (po->pppoe_dev) { - pn = pppoe_pernet(dev_net(po->pppoe_dev)); - delete_item(pn, po->pppoe_pa.sid, - po->pppoe_pa.remote, po->pppoe_ifindex); dev_put(po->pppoe_dev); + po->pppoe_dev = NULL; } + memset(sk_pppox(po) + 1, 0, sizeof(struct pppox_sock) - sizeof(struct sock)); sk->sk_state = PPPOX_NONE; @@ -666,16 +663,15 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, /* Re-bind in session stage only */ if (stage_session(sp->sa_addr.pppoe.sid)) { error = -ENODEV; - dev = dev_get_by_name(sock_net(sk), sp->sa_addr.pppoe.dev); + net = sock_net(sk); + dev = dev_get_by_name(net, sp->sa_addr.pppoe.dev); if (!dev) - goto end; + goto err_put; po->pppoe_dev = dev; po->pppoe_ifindex = dev->ifindex; - pn = pppoe_pernet(dev_net(dev)); - write_lock_bh(&pn->hash_lock); + pn = pppoe_pernet(net); if (!(dev->flags & IFF_UP)) { - write_unlock_bh(&pn->hash_lock); goto err_put; } @@ -683,6 +679,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, &sp->sa_addr.pppoe, sizeof(struct pppoe_addr)); + write_lock_bh(&pn->hash_lock); error = __set_item(pn, po); write_unlock_bh(&pn->hash_lock); if (error < 0) @@ -696,8 +693,11 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, po->chan.ops = &pppoe_chan_ops; error = ppp_register_net_channel(dev_net(dev), &po->chan); - if (error) + if (error) { + delete_item(pn, po->pppoe_pa.sid, + po->pppoe_pa.remote, po->pppoe_ifindex); goto err_put; + } sk->sk_state = PPPOX_CONNECTED; } @@ -915,6 +915,14 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb) struct pppoe_hdr *ph; int data_len = skb->len; + /* The higher-level PPP code (ppp_unregister_channel()) ensures the PPP + * xmit operations conclude prior to an unregistration call. Thus + * sk->sk_state cannot change, so we don't need to do lock_sock(). + * But, we also can't do a lock_sock since that introduces a potential + * deadlock as we'd reverse the lock ordering used when calling + * ppp_unregister_channel(). + */ + if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED)) goto abort; @@ -944,7 +952,6 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb) po->pppoe_pa.remote, NULL, data_len); dev_queue_xmit(skb); - return 1; abort: diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index e7285f01bd04..c2383adcd527 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -95,6 +95,7 @@ enum { /* Misc. stuff */ MAILBOX_COUNT = 16, + MAILBOX_TIMEOUT = 5, PROC_ADDR_RDY = (1 << 31), PROC_ADDR_R = (1 << 30), diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 48b45df85ec9..cea7531f4f40 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3916,6 +3916,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev, goto err_out; } + pci_save_state(pdev); qdev->reg_base = ioremap_nocache(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1)); @@ -4070,6 +4071,33 @@ static void __devexit qlge_remove(struct pci_dev *pdev) free_netdev(ndev); } +/* Clean up resources without touching hardware. */ +static void ql_eeh_close(struct net_device *ndev) +{ + int i; + struct ql_adapter *qdev = netdev_priv(ndev); + + if (netif_carrier_ok(ndev)) { + netif_carrier_off(ndev); + netif_stop_queue(ndev); + } + + if (test_bit(QL_ADAPTER_UP, &qdev->flags)) + cancel_delayed_work_sync(&qdev->asic_reset_work); + cancel_delayed_work_sync(&qdev->mpi_reset_work); + cancel_delayed_work_sync(&qdev->mpi_work); + cancel_delayed_work_sync(&qdev->mpi_idc_work); + cancel_delayed_work_sync(&qdev->mpi_port_cfg_work); + + for (i = 0; i < qdev->rss_ring_count; i++) + netif_napi_del(&qdev->rx_ring[i].napi); + + clear_bit(QL_ADAPTER_UP, &qdev->flags); + ql_tx_ring_clean(qdev); + ql_free_rx_buffers(qdev); + ql_release_adapter_resources(qdev); +} + /* * This callback is called by the PCI subsystem whenever * a PCI bus error is detected. @@ -4078,17 +4106,21 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev, enum pci_channel_state state) { struct net_device *ndev = pci_get_drvdata(pdev); - struct ql_adapter *qdev = netdev_priv(ndev); - - netif_device_detach(ndev); - if (state == pci_channel_io_perm_failure) + switch (state) { + case pci_channel_io_normal: + return PCI_ERS_RESULT_CAN_RECOVER; + case pci_channel_io_frozen: + netif_device_detach(ndev); + if (netif_running(ndev)) + ql_eeh_close(ndev); + pci_disable_device(pdev); + return PCI_ERS_RESULT_NEED_RESET; + case pci_channel_io_perm_failure: + dev_err(&pdev->dev, + "%s: pci_channel_io_perm_failure.\n", __func__); return PCI_ERS_RESULT_DISCONNECT; - - if (netif_running(ndev)) - ql_adapter_down(qdev); - - pci_disable_device(pdev); + } /* Request a slot reset. */ return PCI_ERS_RESULT_NEED_RESET; @@ -4105,25 +4137,15 @@ static pci_ers_result_t qlge_io_slot_reset(struct pci_dev *pdev) struct net_device *ndev = pci_get_drvdata(pdev); struct ql_adapter *qdev = netdev_priv(ndev); + pdev->error_state = pci_channel_io_normal; + + pci_restore_state(pdev); if (pci_enable_device(pdev)) { QPRINTK(qdev, IFUP, ERR, "Cannot re-enable PCI device after reset.\n"); return PCI_ERS_RESULT_DISCONNECT; } - pci_set_master(pdev); - - netif_carrier_off(ndev); - ql_adapter_reset(qdev); - - /* Make sure the EEPROM is good */ - memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len); - - if (!is_valid_ether_addr(ndev->perm_addr)) { - QPRINTK(qdev, IFUP, ERR, "After reset, invalid MAC address.\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - return PCI_ERS_RESULT_RECOVERED; } @@ -4131,17 +4153,21 @@ static void qlge_io_resume(struct pci_dev *pdev) { struct net_device *ndev = pci_get_drvdata(pdev); struct ql_adapter *qdev = netdev_priv(ndev); + int err = 0; - pci_set_master(pdev); - + if (ql_adapter_reset(qdev)) + QPRINTK(qdev, DRV, ERR, "reset FAILED!\n"); if (netif_running(ndev)) { - if (ql_adapter_up(qdev)) { + err = qlge_open(ndev); + if (err) { QPRINTK(qdev, IFUP, ERR, "Device initialization failed after reset.\n"); return; } + } else { + QPRINTK(qdev, IFUP, ERR, + "Device was not running prior to EEH.\n"); } - netif_device_attach(ndev); } diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index 99e58e3f8e22..bcf13c96f73f 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c @@ -470,7 +470,8 @@ end: */ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) { - int status, count; + int status; + unsigned long count; /* Begin polled mode for MPI */ @@ -491,9 +492,9 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) /* Wait for the command to complete. We loop * here because some AEN might arrive while * we're waiting for the mailbox command to - * complete. If more than 5 arrive then we can + * complete. If more than 5 seconds expire we can * assume something is wrong. */ - count = 5; + count = jiffies + HZ * MAILBOX_TIMEOUT; do { /* Wait for the interrupt to come in. */ status = ql_wait_mbx_cmd_cmplt(qdev); @@ -517,15 +518,15 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) MB_CMD_STS_GOOD) || ((mbcp->mbox_out[0] & 0x0000f000) == MB_CMD_STS_INTRMDT)) - break; - } while (--count); + goto done; + } while (time_before(jiffies, count)); - if (!count) { - QPRINTK(qdev, DRV, ERR, - "Timed out waiting for mailbox complete.\n"); - status = -ETIMEDOUT; - goto end; - } + QPRINTK(qdev, DRV, ERR, + "Timed out waiting for mailbox complete.\n"); + status = -ETIMEDOUT; + goto end; + +done: /* Now we can clear the interrupt condition * and look at our status. diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 83c47d95c3aa..fa4935678488 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1029,7 +1029,10 @@ static void rtl8169_vlan_rx_register(struct net_device *dev, spin_lock_irqsave(&tp->lock, flags); tp->vlgrp = grp; - if (tp->vlgrp) + /* + * Do not disable RxVlan on 8110SCd. + */ + if (tp->vlgrp || (tp->mac_version == RTL_GIGA_MAC_VER_05)) tp->cp_cmd |= RxVlan; else tp->cp_cmd &= ~RxVlan; @@ -3197,6 +3200,14 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } rtl8169_init_phy(dev, tp); + + /* + * Pretend we are using VLANs; This bypasses a nasty bug where + * Interrupts stop flowing on high load on 8110SCd controllers. + */ + if (tp->mac_version == RTL_GIGA_MAC_VER_05) + RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | RxVlan); + device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); out: @@ -3368,7 +3379,7 @@ static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) { /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, rx_buf_sz); + RTL_W16(RxMaxSize, rx_buf_sz + 1); } static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c index 01f9432c31ef..98bff5ada09a 100644 --- a/drivers/net/sfc/rx.c +++ b/drivers/net/sfc/rx.c @@ -444,7 +444,8 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue, * the appropriate LRO method */ static void efx_rx_packet_lro(struct efx_channel *channel, - struct efx_rx_buffer *rx_buf) + struct efx_rx_buffer *rx_buf, + bool checksummed) { struct napi_struct *napi = &channel->napi_str; @@ -466,7 +467,8 @@ static void efx_rx_packet_lro(struct efx_channel *channel, skb->len = rx_buf->len; skb->data_len = rx_buf->len; skb->truesize += rx_buf->len; - skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->ip_summed = + checksummed ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE; napi_gro_frags(napi); @@ -475,6 +477,7 @@ out: rx_buf->page = NULL; } else { EFX_BUG_ON_PARANOID(!rx_buf->skb); + EFX_BUG_ON_PARANOID(!checksummed); napi_gro_receive(napi, rx_buf->skb); rx_buf->skb = NULL; @@ -570,7 +573,7 @@ void __efx_rx_packet(struct efx_channel *channel, } if (likely(checksummed || rx_buf->page)) { - efx_rx_packet_lro(channel, rx_buf); + efx_rx_packet_lro(channel, rx_buf, checksummed); goto done; } diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index f49d0800c1d1..528b912a4b0d 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -30,6 +30,7 @@ #include <linux/phy.h> #include <linux/cache.h> #include <linux/io.h> +#include <asm/cacheflush.h> #include "sh_eth.h" diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 2ab5c39f33ca..6a10d7ba5877 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -4538,6 +4538,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev, goto err_out_free_netdev; } + netif_carrier_off(dev); + netif_napi_add(dev, &hw->napi, sky2_poll, NAPI_WEIGHT); err = request_irq(pdev->irq, sky2_intr, diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c index 36cb2423bcf1..75fa32e34fd0 100644 --- a/drivers/net/tokenring/ibmtr.c +++ b/drivers/net/tokenring/ibmtr.c @@ -1144,9 +1144,16 @@ static void dir_open_adapter (struct net_device *dev) } else { char **prphase = printphase; char **prerror = printerror; + int pnr = err / 16 - 1; + int enr = err % 16 - 1; DPRINTK("TR Adapter misc open failure, error code = "); - printk("0x%x, Phase: %s, Error: %s\n", - err, prphase[err/16 -1], prerror[err%16 -1]); + if (pnr < 0 || pnr >= ARRAY_SIZE(printphase) || + enr < 0 || + enr >= ARRAY_SIZE(printerror)) + printk("0x%x, invalid Phase/Error.", err); + else + printk("0x%x, Phase: %s, Error: %s\n", err, + prphase[pnr], prerror[enr]); printk(" retrying after %ds delay...\n", TR_RETRY_INTERVAL/HZ); } diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 72470f77f556..a2b30a10064f 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -649,6 +649,10 @@ static const struct usb_device_id products[] = { USB_DEVICE(0x0fe6, 0x8101), /* DM9601 USB to Fast Ethernet Adapter */ .driver_info = (unsigned long)&dm9601_info, }, + { + USB_DEVICE(0x0a46, 0x9000), /* DM9000E */ + .driver_info = (unsigned long)&dm9601_info, + }, {}, // END }; diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index 0caa8008c51c..f56dec6119c3 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -362,12 +362,12 @@ generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags) retval = -EINVAL; goto halt_fail_and_release; } - dev->hard_mtu = tmp; - net->mtu = dev->hard_mtu - net->hard_header_len; dev_warn(&intf->dev, "dev can't take %u byte packets (max %u), " "adjusting MTU to %u\n", - dev->hard_mtu, tmp, net->mtu); + dev->hard_mtu, tmp, tmp - net->hard_header_len); + dev->hard_mtu = tmp; + net->mtu = dev->hard_mtu - net->hard_header_len; } /* REVISIT: peripheral "alignment" request is ignored ... */ diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 3709d6af9abf..05630f2f6930 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -516,8 +516,7 @@ again: /* Free up any pending old buffers before queueing new ones. */ free_old_xmit_skbs(vi); - /* Put new one in send queue and do transmit */ - __skb_queue_head(&vi->send, skb); + /* Try to transmit */ capacity = xmit_skb(vi, skb); /* This can happen with OOM and indirect buffers. */ @@ -531,8 +530,17 @@ again: } return NETDEV_TX_BUSY; } - vi->svq->vq_ops->kick(vi->svq); + + /* + * Put new one in send queue. You'd expect we'd need this before + * xmit_skb calls add_buf(), since the callback can be triggered + * immediately after that. But since the callback just triggers + * another call back here, normal network xmit locking prevents the + * race. + */ + __skb_queue_head(&vi->send, skb); + /* Don't wait up for transmitted skbs to be freed. */ skb_orphan(skb); nf_reset(skb); diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 7116a1aa20ce..abf896a7390e 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -4790,9 +4790,8 @@ static int proc_stats_rid_open( struct inode *inode, static int get_dec_u16( char *buffer, int *start, int limit ) { u16 value; int valid = 0; - for( value = 0; buffer[*start] >= '0' && - buffer[*start] <= '9' && - *start < limit; (*start)++ ) { + for (value = 0; *start < limit && buffer[*start] >= '0' && + buffer[*start] <= '9'; (*start)++) { valid = 1; value *= 10; value += buffer[*start] - '0'; diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 16a271787b85..1895d63aad0a 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -679,7 +679,7 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc, return rate; if (rate_table->info[rate].valid_single_stream && - !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)); + !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)) return rate; /* This should not happen */ diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 8701034569fa..de4e804bedf0 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -1157,8 +1157,9 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot) } static int dma_tx_fragment(struct b43_dmaring *ring, - struct sk_buff *skb) + struct sk_buff **in_skb) { + struct sk_buff *skb = *in_skb; const struct b43_dma_ops *ops = ring->ops; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); u8 *header; @@ -1224,8 +1225,14 @@ static int dma_tx_fragment(struct b43_dmaring *ring, } memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len); + memcpy(bounce_skb->cb, skb->cb, sizeof(skb->cb)); + bounce_skb->dev = skb->dev; + skb_set_queue_mapping(bounce_skb, skb_get_queue_mapping(skb)); + info = IEEE80211_SKB_CB(bounce_skb); + dev_kfree_skb_any(skb); skb = bounce_skb; + *in_skb = bounce_skb; meta->skb = skb; meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { @@ -1355,7 +1362,11 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb) * static, so we don't need to store it per frame. */ ring->queue_prio = skb_get_queue_mapping(skb); - err = dma_tx_fragment(ring, skb); + /* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing + * into the skb data or cb now. */ + hdr = NULL; + info = NULL; + err = dma_tx_fragment(ring, &skb); if (unlikely(err == -ENOKEY)) { /* Drop this packet, as we don't have the encryption key * anymore and must not transmit it unencrypted. */ diff --git a/drivers/net/wireless/b43/leds.h b/drivers/net/wireless/b43/leds.h index 4c56187810fc..32b66d53cdac 100644 --- a/drivers/net/wireless/b43/leds.h +++ b/drivers/net/wireless/b43/leds.h @@ -1,6 +1,7 @@ #ifndef B43_LEDS_H_ #define B43_LEDS_H_ +struct b43_wl; struct b43_wldev; #ifdef CONFIG_B43_LEDS diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index df6b26a0c05e..86f35827f008 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4501,7 +4501,6 @@ static void b43_op_stop(struct ieee80211_hw *hw) cancel_work_sync(&(wl->beacon_update_trigger)); - wiphy_rfkill_stop_polling(hw->wiphy); mutex_lock(&wl->mutex); if (b43_status(dev) >= B43_STAT_STARTED) { dev = b43_wireless_core_stop(dev); diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index 7a3218c5ba7d..ffdce6f3c909 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c @@ -33,7 +33,8 @@ bool b43_is_hw_radio_enabled(struct b43_wldev *dev) & B43_MMIO_RADIO_HWENABLED_HI_MASK)) return 1; } else { - if (b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO) + if (b43_status(dev) >= B43_STAT_STARTED && + b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO) & B43_MMIO_RADIO_HWENABLED_LO_MASK) return 1; } diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 240cff1e6979..a741d37fd96f 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -6325,8 +6325,10 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, fail: if (dev) { - if (registered) + if (registered) { + unregister_ieee80211(priv->ieee); unregister_netdev(dev); + } ipw2100_hw_stop_adapter(priv); @@ -6383,6 +6385,7 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev) /* Unregister the device first - this results in close() * being called if the device is open. If we free storage * first, then close() will crash. */ + unregister_ieee80211(priv->ieee); unregister_netdev(dev); /* ipw2100_down will ensure that there is no more pending work diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 827824d45de9..9b0f2c0646e0 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -11822,6 +11822,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, if (err) { IPW_ERROR("Failed to register promiscuous network " "device (error %d).\n", err); + unregister_ieee80211(priv->ieee); unregister_netdev(priv->net_dev); goto out_remove_sysfs; } @@ -11872,6 +11873,7 @@ static void __devexit ipw_pci_remove(struct pci_dev *pdev) mutex_unlock(&priv->mutex); + unregister_ieee80211(priv->ieee); unregister_netdev(priv->net_dev); if (priv->rxq) { diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h index bf45391172f3..f42ade6c2d3e 100644 --- a/drivers/net/wireless/ipw2x00/libipw.h +++ b/drivers/net/wireless/ipw2x00/libipw.h @@ -1020,6 +1020,7 @@ static inline int libipw_is_cck_rate(u8 rate) /* ieee80211.c */ extern void free_ieee80211(struct net_device *dev, int monitor); extern struct net_device *alloc_ieee80211(int sizeof_priv, int monitor); +extern void unregister_ieee80211(struct libipw_device *ieee); extern int libipw_change_mtu(struct net_device *dev, int new_mtu); extern void libipw_networks_age(struct libipw_device *ieee, diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c index a0e9f6aed7da..be5b809ec97a 100644 --- a/drivers/net/wireless/ipw2x00/libipw_module.c +++ b/drivers/net/wireless/ipw2x00/libipw_module.c @@ -235,16 +235,19 @@ void free_ieee80211(struct net_device *dev, int monitor) libipw_networks_free(ieee); /* free cfg80211 resources */ - if (!monitor) { - wiphy_unregister(ieee->wdev.wiphy); - kfree(ieee->a_band.channels); - kfree(ieee->bg_band.channels); + if (!monitor) wiphy_free(ieee->wdev.wiphy); - } free_netdev(dev); } +void unregister_ieee80211(struct libipw_device *ieee) +{ + wiphy_unregister(ieee->wdev.wiphy); + kfree(ieee->a_band.channels); + kfree(ieee->bg_band.channels); +} + #ifdef CONFIG_LIBIPW_DEBUG static int debug = 0; @@ -330,3 +333,4 @@ module_init(libipw_init); EXPORT_SYMBOL(alloc_ieee80211); EXPORT_SYMBOL(free_ieee80211); +EXPORT_SYMBOL(unregister_ieee80211); diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index cb8be8d7abc1..5b3672c4d0cc 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -134,7 +134,7 @@ static void spu_transaction_finish(struct if_spi_card *card) static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len) { int err = 0; - u16 reg_out = cpu_to_le16(reg | IF_SPI_WRITE_OPERATION_MASK); + __le16 reg_out = cpu_to_le16(reg | IF_SPI_WRITE_OPERATION_MASK); struct spi_message m; struct spi_transfer reg_trans; struct spi_transfer data_trans; @@ -166,7 +166,7 @@ static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len) static inline int spu_write_u16(struct if_spi_card *card, u16 reg, u16 val) { - u16 buff; + __le16 buff; buff = cpu_to_le16(val); return spu_write(card, reg, (u8 *)&buff, sizeof(u16)); @@ -188,7 +188,7 @@ static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len) { unsigned int delay; int err = 0; - u16 reg_out = cpu_to_le16(reg | IF_SPI_READ_OPERATION_MASK); + __le16 reg_out = cpu_to_le16(reg | IF_SPI_READ_OPERATION_MASK); struct spi_message m; struct spi_transfer reg_trans; struct spi_transfer dummy_trans; @@ -235,7 +235,7 @@ static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len) /* Read 16 bits from an SPI register */ static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val) { - u16 buf; + __le16 buf; int ret; ret = spu_read(card, reg, (u8 *)&buf, sizeof(buf)); @@ -248,7 +248,7 @@ static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val) * The low 16 bits are read first. */ static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val) { - u32 buf; + __le32 buf; int err; err = spu_read(card, reg, (u8 *)&buf, sizeof(buf)); diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 92bc8c5f1ca2..3fac4efa5ac8 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -508,7 +508,7 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp, /* Fill the receive configuration URB and initialise the Rx call back */ usb_fill_bulk_urb(cardp->rx_urb, cardp->udev, usb_rcvbulkpipe(cardp->udev, cardp->ep_in), - (void *) (skb->tail + (size_t) IPFIELD_ALIGN_OFFSET), + skb->data + IPFIELD_ALIGN_OFFSET, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn, cardp); diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 88cd58eb3b9f..1c88c2ea59aa 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -2879,7 +2879,7 @@ static int write_essid(struct file *file, const char __user *buffer, unsigned long count, void *data) { static char proc_essid[33]; - int len = count; + unsigned int len = count; if (len > 32) len = 32; diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index a084077a1c61..9fe770f7d7bb 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -1994,7 +1994,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size); rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID, test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ? - (skbdesc->entry->entry_idx + 1) : 0xff); + txdesc->key_idx : 0xff); rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, skb->len - txdesc->l2pad); rt2x00_set_field32(&word, TXWI_W1_PACKETID, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index b8f5ee33445e..14e7bb210075 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2389,10 +2389,13 @@ static struct usb_device_id rt73usb_device_table[] = { { USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x13b1, 0x0028), USB_DEVICE_DATA(&rt73usb_ops) }, /* MSI */ + { USB_DEVICE(0x0db0, 0x4600), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0db0, 0x6877), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0db0, 0x6874), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0db0, 0xa861), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0db0, 0xa874), USB_DEVICE_DATA(&rt73usb_ops) }, + /* Ovislink */ + { USB_DEVICE(0x1b75, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) }, /* Ralink */ { USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) }, @@ -2420,6 +2423,8 @@ static struct usb_device_id rt73usb_device_table[] = { /* Planex */ { USB_DEVICE(0x2019, 0xab01), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x2019, 0xab50), USB_DEVICE_DATA(&rt73usb_ops) }, + /* WideTell */ + { USB_DEVICE(0x7167, 0x3840), USB_DEVICE_DATA(&rt73usb_ops) }, /* Zcom */ { USB_DEVICE(0x0cde, 0x001c), USB_DEVICE_DATA(&rt73usb_ops) }, /* ZyXEL */ diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index bacaa536fd51..4b22ba568b19 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -97,6 +97,12 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) } EXPORT_SYMBOL(of_mdiobus_register); +/* Helper function for of_phy_find_device */ +static int of_phy_match(struct device *dev, void *phy_np) +{ + return dev_archdata_get_node(&dev->archdata) == phy_np; +} + /** * of_phy_find_device - Give a PHY node, find the phy_device * @phy_np: Pointer to the phy's device tree node @@ -106,15 +112,10 @@ EXPORT_SYMBOL(of_mdiobus_register); struct phy_device *of_phy_find_device(struct device_node *phy_np) { struct device *d; - int match(struct device *dev, void *phy_np) - { - return dev_archdata_get_node(&dev->archdata) == phy_np; - } - if (!phy_np) return NULL; - d = bus_find_device(&mdio_bus_type, NULL, phy_np, match); + d = bus_find_device(&mdio_bus_type, NULL, phy_np, of_phy_match); return d ? to_phy_device(d) : NULL; } EXPORT_SYMBOL(of_phy_find_device); diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 0959430534b2..cb1a027eb552 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -299,17 +299,8 @@ static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned lon r = bus->resource[i]; if (r == &ioport_resource || r == &iomem_resource) continue; - if (r && (r->flags & type_mask) == type) { - if (!r->parent) - return r; - /* - * if there is no child under that, we should release - * and use it. don't need to reset it, pbus_size_* will - * set it again - */ - if (!r->child && !release_resource(r)) - return r; - } + if (r && (r->flags & type_mask) == type && !r->parent) + return r; } return NULL; } diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 4a110b7b2673..6c4a4fc83630 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -1463,7 +1463,9 @@ int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t return -ENOMEM; } tuple.DesiredTuple = code; - tuple.Attributes = TUPLE_RETURN_COMMON; + tuple.Attributes = 0; + if (function == BIND_FN_ALL) + tuple.Attributes = TUPLE_RETURN_COMMON; ret = pccard_get_first_tuple(s, function, &tuple); if (ret != 0) goto done; @@ -1490,7 +1492,7 @@ EXPORT_SYMBOL(pccard_read_tuple); ======================================================================*/ -int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, unsigned int *info) +int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info) { tuple_t *tuple; cisparse_t *p; @@ -1515,30 +1517,30 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, unsigned count = reserved = 0; tuple->DesiredTuple = RETURN_FIRST_TUPLE; tuple->Attributes = TUPLE_RETURN_COMMON; - ret = pccard_get_first_tuple(s, function, tuple); + ret = pccard_get_first_tuple(s, BIND_FN_ALL, tuple); if (ret != 0) goto done; /* First tuple should be DEVICE; we should really have either that or a CFTABLE_ENTRY of some sort */ if ((tuple->TupleCode == CISTPL_DEVICE) || - (pccard_read_tuple(s, function, CISTPL_CFTABLE_ENTRY, p) == 0) || - (pccard_read_tuple(s, function, CISTPL_CFTABLE_ENTRY_CB, p) == 0)) + (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_CFTABLE_ENTRY, p) == 0) || + (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_CFTABLE_ENTRY_CB, p) == 0)) dev_ok++; /* All cards should have a MANFID tuple, and/or a VERS_1 or VERS_2 tuple, for card identification. Certain old D-Link and Linksys cards have only a broken VERS_2 tuple; hence the bogus test. */ - if ((pccard_read_tuple(s, function, CISTPL_MANFID, p) == 0) || - (pccard_read_tuple(s, function, CISTPL_VERS_1, p) == 0) || - (pccard_read_tuple(s, function, CISTPL_VERS_2, p) != -ENOSPC)) + if ((pccard_read_tuple(s, BIND_FN_ALL, CISTPL_MANFID, p) == 0) || + (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_VERS_1, p) == 0) || + (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_VERS_2, p) != -ENOSPC)) ident_ok++; if (!dev_ok && !ident_ok) goto done; for (count = 1; count < MAX_TUPLES; count++) { - ret = pccard_get_next_tuple(s, function, tuple); + ret = pccard_get_next_tuple(s, BIND_FN_ALL, tuple); if (ret != 0) break; if (((tuple->TupleCode > 0x23) && (tuple->TupleCode < 0x40)) || diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 934d4bee39a0..698d75cda084 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -98,10 +98,13 @@ EXPORT_SYMBOL(pcmcia_socket_list_rwsem); * These functions check for the appropriate struct pcmcia_soket arrays, * and pass them to the low-level functions pcmcia_{suspend,resume}_socket */ +static int socket_early_resume(struct pcmcia_socket *skt); +static int socket_late_resume(struct pcmcia_socket *skt); static int socket_resume(struct pcmcia_socket *skt); static int socket_suspend(struct pcmcia_socket *skt); -int pcmcia_socket_dev_suspend(struct device *dev) +static void pcmcia_socket_dev_run(struct device *dev, + int (*cb)(struct pcmcia_socket *)) { struct pcmcia_socket *socket; @@ -110,29 +113,34 @@ int pcmcia_socket_dev_suspend(struct device *dev) if (socket->dev.parent != dev) continue; mutex_lock(&socket->skt_mutex); - socket_suspend(socket); + cb(socket); mutex_unlock(&socket->skt_mutex); } up_read(&pcmcia_socket_list_rwsem); +} +int pcmcia_socket_dev_suspend(struct device *dev) +{ + pcmcia_socket_dev_run(dev, socket_suspend); return 0; } EXPORT_SYMBOL(pcmcia_socket_dev_suspend); -int pcmcia_socket_dev_resume(struct device *dev) +void pcmcia_socket_dev_early_resume(struct device *dev) { - struct pcmcia_socket *socket; + pcmcia_socket_dev_run(dev, socket_early_resume); +} +EXPORT_SYMBOL(pcmcia_socket_dev_early_resume); - down_read(&pcmcia_socket_list_rwsem); - list_for_each_entry(socket, &pcmcia_socket_list, socket_list) { - if (socket->dev.parent != dev) - continue; - mutex_lock(&socket->skt_mutex); - socket_resume(socket); - mutex_unlock(&socket->skt_mutex); - } - up_read(&pcmcia_socket_list_rwsem); +void pcmcia_socket_dev_late_resume(struct device *dev) +{ + pcmcia_socket_dev_run(dev, socket_late_resume); +} +EXPORT_SYMBOL(pcmcia_socket_dev_late_resume); +int pcmcia_socket_dev_resume(struct device *dev) +{ + pcmcia_socket_dev_run(dev, socket_resume); return 0; } EXPORT_SYMBOL(pcmcia_socket_dev_resume); @@ -546,29 +554,24 @@ static int socket_suspend(struct pcmcia_socket *skt) return 0; } -/* - * Resume a socket. If a card is present, verify its CIS against - * our cached copy. If they are different, the card has been - * replaced, and we need to tell the drivers. - */ -static int socket_resume(struct pcmcia_socket *skt) +static int socket_early_resume(struct pcmcia_socket *skt) { - int ret; - - if (!(skt->state & SOCKET_SUSPEND)) - return -EBUSY; - skt->socket = dead_socket; skt->ops->init(skt); skt->ops->set_socket(skt, &skt->socket); + if (skt->state & SOCKET_PRESENT) + skt->resume_status = socket_setup(skt, resume_delay); + return 0; +} +static int socket_late_resume(struct pcmcia_socket *skt) +{ if (!(skt->state & SOCKET_PRESENT)) { skt->state &= ~SOCKET_SUSPEND; return socket_insert(skt); } - ret = socket_setup(skt, resume_delay); - if (ret == 0) { + if (skt->resume_status == 0) { /* * FIXME: need a better check here for cardbus cards. */ @@ -596,6 +599,20 @@ static int socket_resume(struct pcmcia_socket *skt) return 0; } +/* + * Resume a socket. If a card is present, verify its CIS against + * our cached copy. If they are different, the card has been + * replaced, and we need to tell the drivers. + */ +static int socket_resume(struct pcmcia_socket *skt) +{ + if (!(skt->state & SOCKET_SUSPEND)) + return -EBUSY; + + socket_early_resume(skt); + return socket_late_resume(skt); +} + static void socket_remove(struct pcmcia_socket *skt) { dev_printk(KERN_NOTICE, &skt->dev, diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index 79615e6d540b..1f4098f1354d 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -197,8 +197,7 @@ int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t code, void *parse); int pcmcia_replace_cis(struct pcmcia_socket *s, const u8 *data, const size_t len); -int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, - unsigned int *count); +int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *count); /* rsrc_mgr.c */ int pcmcia_validate_mem(struct pcmcia_socket *s); diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 9f300d3cb125..f5b7079f13d3 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -547,7 +547,7 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev) if (!vers1) return -ENOMEM; - if (!pccard_read_tuple(p_dev->socket, p_dev->func, + if (!pccard_read_tuple(p_dev->socket, BIND_FN_ALL, CISTPL_MANFID, &manf_id)) { p_dev->manf_id = manf_id.manf; p_dev->card_id = manf_id.card; @@ -581,9 +581,9 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev) kfree(devgeo); } - if (!pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_VERS_1, + if (!pccard_read_tuple(p_dev->socket, BIND_FN_ALL, CISTPL_VERS_1, vers1)) { - for (i=0; i < vers1->ns; i++) { + for (i = 0; i < min_t(unsigned int, 4, vers1->ns); i++) { char *tmp; unsigned int length; @@ -733,7 +733,7 @@ static int pcmcia_card_add(struct pcmcia_socket *s) return -EAGAIN; /* try again, but later... */ } - ret = pccard_validate_cis(s, BIND_FN_ALL, &no_chains); + ret = pccard_validate_cis(s, &no_chains); if (ret || !no_chains) { ds_dev_dbg(0, &s->dev, "invalid CIS or invalid resources\n"); return -ENODEV; diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index b906abe26ad0..a4aacb830b80 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c @@ -1053,8 +1053,8 @@ static int i365_set_io_map(u_short sock, struct pccard_io_map *io) u_char map, ioctl; debug(1, "SetIOMap(%d, %d, %#2.2x, %d ns, " - "%#x-%#x)\n", sock, io->map, io->flags, - io->speed, io->start, io->stop); + "%#llx-%#llx)\n", sock, io->map, io->flags, io->speed, + (unsigned long long)io->start, (unsigned long long)io->stop); map = io->map; if ((map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) || (io->stop < io->start)) return -EINVAL; diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c index d1d89c4491ad..7dfbee1dcd76 100644 --- a/drivers/pcmcia/m32r_cfc.c +++ b/drivers/pcmcia/m32r_cfc.c @@ -537,8 +537,9 @@ static int _pcc_set_io_map(u_short sock, struct pccard_io_map *io) u_char map; debug(3, "m32r_cfc: SetIOMap(%d, %d, %#2.2x, %d ns, " - "%#lx-%#lx)\n", sock, io->map, io->flags, - io->speed, io->start, io->stop); + "%#llx-%#llx)\n", sock, io->map, io->flags, + io->speed, (unsigned long long)io->start, + (unsigned long long)io->stop); map = io->map; return 0; @@ -554,8 +555,9 @@ static int _pcc_set_mem_map(u_short sock, struct pccard_mem_map *mem) pcc_socket_t *t = &socket[sock]; debug(3, "m32r_cfc: SetMemMap(%d, %d, %#2.2x, %d ns, " - "%#lx, %#x)\n", sock, map, mem->flags, - mem->speed, mem->static_start, mem->card_start); + "%#llx, %#x)\n", sock, map, mem->flags, + mem->speed, (unsigned long long)mem->static_start, + mem->card_start); /* * sanity check diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c index a0655839c8d3..c6524f99ccc3 100644 --- a/drivers/pcmcia/m32r_pcc.c +++ b/drivers/pcmcia/m32r_pcc.c @@ -492,8 +492,9 @@ static int _pcc_set_io_map(u_short sock, struct pccard_io_map *io) u_char map; debug(3, "m32r-pcc: SetIOMap(%d, %d, %#2.2x, %d ns, " - "%#x-%#x)\n", sock, io->map, io->flags, - io->speed, io->start, io->stop); + "%#llx-%#llx)\n", sock, io->map, io->flags, + io->speed, (unsigned long long)io->start, + (unsigned long long)io->stop); map = io->map; return 0; @@ -515,8 +516,9 @@ static int _pcc_set_mem_map(u_short sock, struct pccard_mem_map *mem) #endif debug(3, "m32r-pcc: SetMemMap(%d, %d, %#2.2x, %d ns, " - "%#lx, %#x)\n", sock, map, mem->flags, - mem->speed, mem->static_start, mem->card_start); + "%#llx, %#x)\n", sock, map, mem->flags, + mem->speed, (unsigned long long)mem->static_start, + mem->card_start); /* * sanity check diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c index c69f2c4fe520..403559ba49dd 100644 --- a/drivers/pcmcia/m8xx_pcmcia.c +++ b/drivers/pcmcia/m8xx_pcmcia.c @@ -975,8 +975,9 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) #define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start) dprintk("SetIOMap(%d, %d, %#2.2x, %d ns, " - "%#4.4x-%#4.4x)\n", lsock, io->map, io->flags, - io->speed, io->start, io->stop); + "%#4.4llx-%#4.4llx)\n", lsock, io->map, io->flags, + io->speed, (unsigned long long)io->start, + (unsigned long long)io->stop); if ((io->map >= PCMCIA_IO_WIN_NO) || (io->start > 0xffff) || (io->stop > 0xffff) || (io->stop < io->start)) @@ -1055,8 +1056,9 @@ static int m8xx_set_mem_map(struct pcmcia_socket *sock, pcmconf8xx_t *pcmcia = s->pcmcia; dprintk("SetMemMap(%d, %d, %#2.2x, %d ns, " - "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags, - mem->speed, mem->static_start, mem->card_start); + "%#5.5llx, %#5.5x)\n", lsock, mem->map, mem->flags, + mem->speed, (unsigned long long)mem->static_start, + mem->card_start); if ((mem->map >= PCMCIA_MEM_WIN_NO) // || ((mem->s) >= PCMCIA_MEM_WIN_SIZE) @@ -1107,8 +1109,9 @@ static int m8xx_set_mem_map(struct pcmcia_socket *sock, } dprintk("SetMemMap(%d, %d, %#2.2x, %d ns, " - "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags, - mem->speed, mem->static_start, mem->card_start); + "%#5.5llx, %#5.5x)\n", lsock, mem->map, mem->flags, + mem->speed, (unsigned long long)mem->static_start, + mem->card_start); /* copy the struct and modify the copy */ diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index 32c44040c1e8..30cf71d2ee23 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c @@ -881,7 +881,7 @@ static int ds_ioctl(struct inode * inode, struct file * file, mutex_lock(&s->skt_mutex); pcmcia_validate_mem(s); mutex_unlock(&s->skt_mutex); - ret = pccard_validate_cis(s, BIND_FN_ALL, &buf->cisinfo.Chains); + ret = pccard_validate_cis(s, &buf->cisinfo.Chains); break; case DS_SUSPEND_CARD: ret = pcmcia_suspend_card(s); diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c index 1c39d3438f20..70a33468bcd0 100644 --- a/drivers/pcmcia/pd6729.c +++ b/drivers/pcmcia/pd6729.c @@ -641,6 +641,12 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev, if ((ret = pci_enable_device(dev))) goto err_out_free_mem; + if (!pci_resource_start(dev, 0)) { + printk(KERN_INFO "pd6729: refusing to load the driver " + "as the io_base is 0.\n"); + goto err_out_free_mem; + } + printk(KERN_INFO "pd6729: Cirrus PD6729 PCI to PCMCIA Bridge " "at 0x%llx on irq %d\n", (unsigned long long)pci_resource_start(dev, 0), dev->irq); diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 9ca22c7aafb2..7039f3cf5b77 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -206,6 +206,7 @@ static void do_io_probe(struct pcmcia_socket *s, unsigned int base, /* First, what does a floating port look like? */ b = kzalloc(256, GFP_KERNEL); if (!b) { + printk("\n"); dev_printk(KERN_ERR, &s->dev, "do_io_probe: unable to kmalloc 256 bytes"); return; @@ -275,7 +276,7 @@ static int readable(struct pcmcia_socket *s, struct resource *res, s->cis_mem.res = res; s->cis_virt = ioremap(res->start, s->map_size); if (s->cis_virt) { - ret = pccard_validate_cis(s, BIND_FN_ALL, count); + ret = pccard_validate_cis(s, count); /* invalidate mapping and CIS cache */ iounmap(s->cis_virt); s->cis_virt = NULL; diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c index 163cf98e2386..ef7e9e58782b 100644 --- a/drivers/pcmcia/soc_common.c +++ b/drivers/pcmcia/soc_common.c @@ -336,8 +336,9 @@ soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *m struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); unsigned short speed = map->speed; - debug(skt, 2, "map %u speed %u start 0x%08x stop 0x%08x\n", - map->map, map->speed, map->start, map->stop); + debug(skt, 2, "map %u speed %u start 0x%08llx stop 0x%08llx\n", + map->map, map->speed, (unsigned long long)map->start, + (unsigned long long)map->stop); debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n", (map->flags==0)?"<NONE>":"", (map->flags&MAP_ACTIVE)?"ACTIVE ":"", diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index ff9a3bb3c88d..78d5aab542f7 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c @@ -300,7 +300,7 @@ static ssize_t pccard_show_cis(struct kobject *kobj, if (!(s->state & SOCKET_PRESENT)) return -ENODEV; - if (pccard_validate_cis(s, BIND_FN_ALL, &chains)) + if (pccard_validate_cis(s, &chains)) return -EIO; if (!chains) return -ENODATA; diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c index 582413fcb62f..6918849d511e 100644 --- a/drivers/pcmcia/tcic.c +++ b/drivers/pcmcia/tcic.c @@ -732,8 +732,8 @@ static int tcic_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) u_short base, len, ioctl; debug(1, "SetIOMap(%d, %d, %#2.2x, %d ns, " - "%#x-%#x)\n", psock, io->map, io->flags, - io->speed, io->start, io->stop); + "%#llx-%#llx)\n", psock, io->map, io->flags, io->speed, + (unsigned long long)io->start, (unsigned long long)io->stop); if ((io->map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) || (io->stop < io->start)) return -EINVAL; tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT)); diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index abe0e44c6e9e..8be4cc447a17 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -1275,16 +1275,26 @@ static int yenta_dev_resume_noirq(struct device *dev) if (socket->type && socket->type->restore_state) socket->type->restore_state(socket); - return pcmcia_socket_dev_resume(dev); + pcmcia_socket_dev_early_resume(dev); + return 0; +} + +static int yenta_dev_resume(struct device *dev) +{ + pcmcia_socket_dev_late_resume(dev); + return 0; } static struct dev_pm_ops yenta_pm_ops = { .suspend_noirq = yenta_dev_suspend_noirq, .resume_noirq = yenta_dev_resume_noirq, + .resume = yenta_dev_resume, .freeze_noirq = yenta_dev_suspend_noirq, .thaw_noirq = yenta_dev_resume_noirq, + .thaw = yenta_dev_resume, .poweroff_noirq = yenta_dev_suspend_noirq, .restore_noirq = yenta_dev_resume_noirq, + .restore = yenta_dev_resume, }; #define YENTA_PM_OPS (¥ta_pm_ops) diff --git a/drivers/s390/char/sclp_async.c b/drivers/s390/char/sclp_async.c index a4f68e5b9c96..b44462a6c6d3 100644 --- a/drivers/s390/char/sclp_async.c +++ b/drivers/s390/char/sclp_async.c @@ -26,7 +26,6 @@ static struct sclp_async_sccb *sccb; static int sclp_async_send_wait(char *message); static struct ctl_table_header *callhome_sysctl_header; static DEFINE_SPINLOCK(sclp_async_lock); -static char nodename[64]; #define SCLP_NORMAL_WRITE 0x00 struct async_evbuf { @@ -52,9 +51,10 @@ static struct sclp_register sclp_async_register = { static int call_home_on_panic(struct notifier_block *self, unsigned long event, void *data) { - strncat(data, nodename, strlen(nodename)); - sclp_async_send_wait(data); - return NOTIFY_DONE; + strncat(data, init_utsname()->nodename, + sizeof(init_utsname()->nodename)); + sclp_async_send_wait(data); + return NOTIFY_DONE; } static struct notifier_block call_home_panic_nb = { @@ -68,15 +68,14 @@ static int proc_handler_callhome(struct ctl_table *ctl, int write, { unsigned long val; int len, rc; - char buf[2]; + char buf[3]; - if (!*count | (*ppos && !write)) { + if (!*count || (*ppos && !write)) { *count = 0; return 0; } if (!write) { - len = sprintf(buf, "%d\n", callhome_enabled); - buf[len] = '\0'; + len = snprintf(buf, sizeof(buf), "%d\n", callhome_enabled); rc = copy_to_user(buffer, buf, sizeof(buf)); if (rc != 0) return -EFAULT; @@ -171,39 +170,29 @@ static int __init sclp_async_init(void) rc = sclp_register(&sclp_async_register); if (rc) return rc; - callhome_sysctl_header = register_sysctl_table(kern_dir_table); - if (!callhome_sysctl_header) { - rc = -ENOMEM; - goto out_sclp; - } - if (!(sclp_async_register.sclp_receive_mask & EVTYP_ASYNC_MASK)) { - rc = -EOPNOTSUPP; + rc = -EOPNOTSUPP; + if (!(sclp_async_register.sclp_receive_mask & EVTYP_ASYNC_MASK)) goto out_sclp; - } rc = -ENOMEM; + callhome_sysctl_header = register_sysctl_table(kern_dir_table); + if (!callhome_sysctl_header) + goto out_sclp; request = kzalloc(sizeof(struct sclp_req), GFP_KERNEL); - if (!request) - goto out_sys; sccb = (struct sclp_async_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA); - if (!sccb) + if (!request || !sccb) goto out_mem; - rc = atomic_notifier_chain_register(&panic_notifier_list, - &call_home_panic_nb); - if (rc) - goto out_mem; - - strncpy(nodename, init_utsname()->nodename, 64); - return 0; - + rc = atomic_notifier_chain_register(&panic_notifier_list, + &call_home_panic_nb); + if (!rc) + goto out; out_mem: kfree(request); free_page((unsigned long) sccb); -out_sys: unregister_sysctl_table(callhome_sysctl_header); out_sclp: sclp_unregister(&sclp_async_register); +out: return rc; - } module_init(sclp_async_init); diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c index 102000d1af6f..3012355f8304 100644 --- a/drivers/s390/net/smsgiucv.c +++ b/drivers/s390/net/smsgiucv.c @@ -158,7 +158,12 @@ static int smsg_pm_restore_thaw(struct device *dev) smsg_path->flags = 0; rc = iucv_path_connect(smsg_path, &smsg_handler, "*MSG ", NULL, NULL, NULL); - printk(KERN_ERR "iucv_path_connect returned with rc %i\n", rc); +#ifdef CONFIG_PM_DEBUG + if (rc) + printk(KERN_ERR + "iucv_path_connect returned with rc %i\n", rc); +#endif + cpcmd("SET SMSG IUCV", NULL, 0, NULL); } return 0; } diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 0f79f3af4f54..2889e5f2dfd3 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -128,12 +128,13 @@ out_ccwdev: static void __init zfcp_init_device_setup(char *devstr) { char *token; - char *str; + char *str, *str_saved; char busid[ZFCP_BUS_ID_SIZE]; u64 wwpn, lun; /* duplicate devstr and keep the original for sysfs presentation*/ - str = kmalloc(strlen(devstr) + 1, GFP_KERNEL); + str_saved = kmalloc(strlen(devstr) + 1, GFP_KERNEL); + str = str_saved; if (!str) return; @@ -152,12 +153,12 @@ static void __init zfcp_init_device_setup(char *devstr) if (!token || strict_strtoull(token, 0, (unsigned long long *) &lun)) goto err_out; - kfree(str); + kfree(str_saved); zfcp_init_device_configure(busid, wwpn, lun); return; - err_out: - kfree(str); +err_out: + kfree(str_saved); pr_err("%s is not a valid SCSI device\n", devstr); } diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 73d366ba31e5..f73e2180f333 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -858,10 +858,7 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) return zfcp_erp_open_ptp_port(act); if (!port->d_id) { - zfcp_port_get(port); - if (!queue_work(adapter->work_queue, - &port->gid_pn_work)) - zfcp_port_put(port); + zfcp_fc_trigger_did_lookup(port); return ZFCP_ERP_EXIT; } return zfcp_erp_port_strategy_open_port(act); @@ -869,12 +866,11 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) case ZFCP_ERP_STEP_PORT_OPENING: /* D_ID might have changed during open */ if (p_status & ZFCP_STATUS_COMMON_OPEN) { - if (port->d_id) - return ZFCP_ERP_SUCCEEDED; - else { - act->step = ZFCP_ERP_STEP_PORT_CLOSING; - return ZFCP_ERP_CONTINUES; + if (!port->d_id) { + zfcp_fc_trigger_did_lookup(port); + return ZFCP_ERP_EXIT; } + return ZFCP_ERP_SUCCEEDED; } if (port->d_id && !(p_status & ZFCP_STATUS_COMMON_NOESC)) { port->d_id = 0; @@ -889,19 +885,21 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action) { struct zfcp_port *port = erp_action->port; + int p_status = atomic_read(&port->status); - if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC) + if ((p_status & ZFCP_STATUS_COMMON_NOESC) && + !(p_status & ZFCP_STATUS_COMMON_OPEN)) goto close_init_done; switch (erp_action->step) { case ZFCP_ERP_STEP_UNINITIALIZED: zfcp_erp_port_strategy_clearstati(port); - if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN) + if (p_status & ZFCP_STATUS_COMMON_OPEN) return zfcp_erp_port_strategy_close(erp_action); break; case ZFCP_ERP_STEP_PORT_CLOSING: - if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN) + if (p_status & ZFCP_STATUS_COMMON_OPEN) return ZFCP_ERP_FAILED; break; } diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 629edec70405..b3f28deb4505 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -96,6 +96,7 @@ extern int zfcp_fc_scan_ports(struct zfcp_adapter *); extern void _zfcp_fc_scan_ports_later(struct work_struct *); extern void zfcp_fc_incoming_els(struct zfcp_fsf_req *); extern void zfcp_fc_port_did_lookup(struct work_struct *); +extern void zfcp_fc_trigger_did_lookup(struct zfcp_port *); extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *); extern void zfcp_fc_test_link(struct zfcp_port *); extern void zfcp_fc_link_test_work(struct work_struct *); diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 722f22de8753..df23bcead23d 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -361,6 +361,17 @@ out: } /** + * zfcp_fc_trigger_did_lookup - trigger the d_id lookup using a GID_PN request + * @port: The zfcp_port to lookup the d_id for. + */ +void zfcp_fc_trigger_did_lookup(struct zfcp_port *port) +{ + zfcp_port_get(port); + if (!queue_work(port->adapter->work_queue, &port->gid_pn_work)) + zfcp_port_put(port); +} + +/** * zfcp_fc_plogi_evaluate - evaluate PLOGI playload * @port: zfcp_port structure * @plogi: plogi payload diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 38a7e4a6b639..4e41baa0c141 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -1079,7 +1079,7 @@ static int zfcp_fsf_setup_ct_els(struct zfcp_fsf_req *req, /* common settings for ct/gs and els requests */ req->qtcb->bottom.support.service_class = FSF_CLASS_3; req->qtcb->bottom.support.timeout = 2 * R_A_TOV; - zfcp_fsf_start_timer(req, 2 * R_A_TOV + 10); + zfcp_fsf_start_timer(req, (2 * R_A_TOV + 10) * HZ); return 0; } @@ -1475,9 +1475,16 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els; if (req->qtcb->bottom.support.els1_length >= FSF_PLOGI_MIN_LEN) { - if (plogi->serv_param.wwpn != port->wwpn) + if (plogi->serv_param.wwpn != port->wwpn) { port->d_id = 0; - else { + dev_warn(&port->adapter->ccw_device->dev, + "A port opened with WWPN 0x%016Lx " + "returned data that identifies it as " + "WWPN 0x%016Lx\n", + (unsigned long long) port->wwpn, + (unsigned long long) + plogi->serv_param.wwpn); + } else { port->wwnn = plogi->serv_param.wwnn; zfcp_fc_plogi_evaluate(port, plogi); } diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index 079a8cf518a3..d31000886ca8 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c @@ -224,6 +224,7 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev, zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL); zfcp_erp_wait(unit->port->adapter); + flush_work(&unit->scsi_work); zfcp_unit_put(unit); out: mutex_unlock(&zfcp_data.config_mutex); diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index b6af63ca980b..496764349c41 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -1918,6 +1918,10 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg) } size = size>>16; size *= 4; + if (size > MAX_MESSAGE_SIZE) { + rcode = -EINVAL; + goto cleanup; + } /* Copy in the user's I2O command */ if (copy_from_user (msg, user_msg, size)) { rcode = -EFAULT; diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index c44783801402..0547a7f44d42 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -317,6 +317,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, out_device_destroy: scsi_device_set_state(sdev, SDEV_DEL); transport_destroy_device(&sdev->sdev_gendev); + put_device(&sdev->sdev_dev); put_device(&sdev->sdev_gendev); out: if (display_failure_msg) @@ -957,6 +958,7 @@ static inline void scsi_destroy_sdev(struct scsi_device *sdev) if (sdev->host->hostt->slave_destroy) sdev->host->hostt->slave_destroy(sdev); transport_destroy_device(&sdev->sdev_gendev); + put_device(&sdev->sdev_dev); put_device(&sdev->sdev_gendev); } diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index fde54537d715..5c7eb63a19d1 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -864,10 +864,6 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) goto clean_device; } - /* take a reference for the sdev_dev; this is - * released by the sdev_class .release */ - get_device(&sdev->sdev_gendev); - /* create queue files, which may be writable, depending on the host */ if (sdev->host->hostt->change_queue_depth) error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_depth_rw); @@ -917,6 +913,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) device_del(&sdev->sdev_gendev); transport_destroy_device(&sdev->sdev_gendev); + put_device(&sdev->sdev_dev); put_device(&sdev->sdev_gendev); return error; @@ -1065,7 +1062,7 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev) sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); device_initialize(&sdev->sdev_dev); - sdev->sdev_dev.parent = &sdev->sdev_gendev; + sdev->sdev_dev.parent = get_device(&sdev->sdev_gendev); sdev->sdev_dev.class = &sdev_class; dev_set_name(&sdev->sdev_dev, "%d:%d:%d:%d", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index e7108e75653d..42e8550cd2b6 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -1561,11 +1561,16 @@ enum pci_board_num_t { pbn_exar_XR17C152, pbn_exar_XR17C154, pbn_exar_XR17C158, + pbn_exar_ibm_saturn, pbn_pasemi_1682M, pbn_ni8430_2, pbn_ni8430_4, pbn_ni8430_8, pbn_ni8430_16, + pbn_ADDIDATA_PCIe_1_3906250, + pbn_ADDIDATA_PCIe_2_3906250, + pbn_ADDIDATA_PCIe_4_3906250, + pbn_ADDIDATA_PCIe_8_3906250, }; /* @@ -2146,6 +2151,13 @@ static struct pciserial_board pci_boards[] __devinitdata = { .base_baud = 921600, .uart_offset = 0x200, }, + [pbn_exar_ibm_saturn] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 921600, + .uart_offset = 0x200, + }, + /* * PA Semi PWRficient PA6T-1682M on-chip UART */ @@ -2185,6 +2197,37 @@ static struct pciserial_board pci_boards[] __devinitdata = { .uart_offset = 0x10, .first_offset = 0x800, }, + /* + * ADDI-DATA GmbH PCI-Express communication cards <info@addi-data.com> + */ + [pbn_ADDIDATA_PCIe_1_3906250] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 3906250, + .uart_offset = 0x200, + .first_offset = 0x1000, + }, + [pbn_ADDIDATA_PCIe_2_3906250] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 3906250, + .uart_offset = 0x200, + .first_offset = 0x1000, + }, + [pbn_ADDIDATA_PCIe_4_3906250] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 3906250, + .uart_offset = 0x200, + .first_offset = 0x1000, + }, + [pbn_ADDIDATA_PCIe_8_3906250] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 3906250, + .uart_offset = 0x200, + .first_offset = 0x1000, + }, }; static const struct pci_device_id softmodem_blacklist[] = { @@ -2649,6 +2692,9 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_SUBVENDOR_ID_CONNECT_TECH, PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485, 0, 0, pbn_b0_8_1843200_200 }, + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152, + PCI_VENDOR_ID_IBM, PCI_SUBDEVICE_ID_IBM_SATURN_SERIAL_ONE_PORT, + 0, 0, pbn_exar_ibm_saturn }, { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530, PCI_ANY_ID, PCI_ANY_ID, 0, 0, @@ -3556,6 +3602,38 @@ static struct pci_device_id serial_pci_tbl[] = { 0, pbn_b0_8_115200 }, + { PCI_VENDOR_ID_ADDIDATA, + PCI_DEVICE_ID_ADDIDATA_APCIe7500, + PCI_ANY_ID, + PCI_ANY_ID, + 0, + 0, + pbn_ADDIDATA_PCIe_4_3906250 }, + + { PCI_VENDOR_ID_ADDIDATA, + PCI_DEVICE_ID_ADDIDATA_APCIe7420, + PCI_ANY_ID, + PCI_ANY_ID, + 0, + 0, + pbn_ADDIDATA_PCIe_2_3906250 }, + + { PCI_VENDOR_ID_ADDIDATA, + PCI_DEVICE_ID_ADDIDATA_APCIe7300, + PCI_ANY_ID, + PCI_ANY_ID, + 0, + 0, + pbn_ADDIDATA_PCIe_1_3906250 }, + + { PCI_VENDOR_ID_ADDIDATA, + PCI_DEVICE_ID_ADDIDATA_APCIe7800, + PCI_ANY_ID, + PCI_ANY_ID, + 0, + 0, + pbn_ADDIDATA_PCIe_8_3906250 }, + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835, PCI_VENDOR_ID_IBM, 0x0299, 0, 0, pbn_b0_bt_2_115200 }, diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 3551c5cb7094..9d948bccafaf 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -1531,7 +1531,7 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev) void *data; int ret; - BUILD_BUG_ON(!is_power_of_2(ATMEL_SERIAL_RINGSIZE)); + BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1)); port = &atmel_ports[pdev->id]; port->backup_imr = 0; diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index d7bcd074d383..7ce9e9f567a3 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -705,7 +705,7 @@ mpc52xx_uart_verify_port(struct uart_port *port, struct serial_struct *ser) return -EINVAL; if ((ser->irq != port->irq) || - (ser->io_type != SERIAL_IO_MEM) || + (ser->io_type != UPIO_MEM) || (ser->baud_base != port->uartclk) || (ser->iomem_base != (void *)port->mapbase) || (ser->hub6 != 0)) diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index ff4617e21426..7c7914f5fa02 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -879,10 +879,10 @@ static struct pcmcia_device_id serial_ids[] = { PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "cis/DP83903.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "cis/3CXEM556.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "cis/3CXEM556.cis"), - PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC850", 0xd85f6206, 0x42a2c018, "SW_8xx_SER.cis"), /* Sierra Wireless AC850 3G Network Adapter R1 */ - PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0x0710, "SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */ - PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */ - PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */ + PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC850", 0xd85f6206, 0x42a2c018, "cis/SW_8xx_SER.cis"), /* Sierra Wireless AC850 3G Network Adapter R1 */ + PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC710/AC750", 0xd85f6206, 0x761b11e0, "cis/SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */ + PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "cis/SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */ + PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "cis/SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */ PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "cis/MT5634ZLX.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-2", 0x96913a85, 0x27ab5437, "cis/COMpad2.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "cis/COMpad4.cis"), diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 7df3ba4f1f4d..d21b3469f6d7 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -93,8 +93,6 @@ source "drivers/staging/dst/Kconfig" source "drivers/staging/pohmelfs/Kconfig" -source "drivers/staging/stlc45xx/Kconfig" - source "drivers/staging/b3dfg/Kconfig" source "drivers/staging/phison/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 747571172269..8cbf1aebea2e 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -29,7 +29,6 @@ obj-$(CONFIG_ANDROID) += android/ obj-$(CONFIG_ANDROID) += dream/ obj-$(CONFIG_DST) += dst/ obj-$(CONFIG_POHMELFS) += pohmelfs/ -obj-$(CONFIG_STLC45XX) += stlc45xx/ obj-$(CONFIG_B3DFG) += b3dfg/ obj-$(CONFIG_IDE_PHISON) += phison/ obj-$(CONFIG_PLAN9AUTH) += p9auth/ diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 247194992374..eb675635ae60 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -2,6 +2,7 @@ menu "Android" config ANDROID bool "Android Drivers" + depends on BROKEN default N ---help--- Enable support for various drivers needed on the Android platform diff --git a/drivers/staging/hv/ChannelMgmt.h b/drivers/staging/hv/ChannelMgmt.h index a839d8fe6cec..fa973d86b624 100644 --- a/drivers/staging/hv/ChannelMgmt.h +++ b/drivers/staging/hv/ChannelMgmt.h @@ -26,6 +26,7 @@ #define _CHANNEL_MGMT_H_ #include <linux/list.h> +#include <linux/timer.h> #include "RingBuffer.h" #include "VmbusChannelInterface.h" #include "VmbusPacketFormat.h" @@ -54,7 +55,7 @@ enum vmbus_channel_message_type { ChannelMessageViewRangeRemove = 18, #endif ChannelMessageCount -} __attribute__((packed)); +}; struct vmbus_channel_message_header { enum vmbus_channel_message_type MessageType; diff --git a/drivers/staging/hv/NetVsc.c b/drivers/staging/hv/NetVsc.c index 1610b845198f..d384c0ddf069 100644 --- a/drivers/staging/hv/NetVsc.c +++ b/drivers/staging/hv/NetVsc.c @@ -1052,7 +1052,7 @@ static void NetVscOnReceive(struct hv_device *Device, */ spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags); while (!list_empty(&netDevice->ReceivePacketList)) { - list_move_tail(&netDevice->ReceivePacketList, &listHead); + list_move_tail(netDevice->ReceivePacketList.next, &listHead); if (++count == vmxferpagePacket->RangeCount + 1) break; } @@ -1071,7 +1071,7 @@ static void NetVscOnReceive(struct hv_device *Device, /* Return it to the freelist */ spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags); for (i = count; i != 0; i--) { - list_move_tail(&listHead, + list_move_tail(listHead.next, &netDevice->ReceivePacketList); } spin_unlock_irqrestore(&netDevice->receive_packet_list_lock, @@ -1085,8 +1085,7 @@ static void NetVscOnReceive(struct hv_device *Device, } /* Remove the 1st packet to represent the xfer page packet itself */ - xferpagePacket = list_entry(&listHead, struct xferpage_packet, - ListEntry); + xferpagePacket = (struct xferpage_packet*)listHead.next; list_del(&xferpagePacket->ListEntry); /* This is how much we can satisfy */ @@ -1102,8 +1101,7 @@ static void NetVscOnReceive(struct hv_device *Device, /* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */ for (i = 0; i < (count - 1); i++) { - netvscPacket = list_entry(&listHead, struct hv_netvsc_packet, - ListEntry); + netvscPacket = (struct hv_netvsc_packet*)listHead.next; list_del(&netvscPacket->ListEntry); /* Initialize the netvsc packet */ diff --git a/drivers/staging/hv/TODO b/drivers/staging/hv/TODO index 4d390b237742..dbfbde937a66 100644 --- a/drivers/staging/hv/TODO +++ b/drivers/staging/hv/TODO @@ -1,11 +1,17 @@ TODO: - fix remaining checkpatch warnings and errors + - use of /** when it is not a kerneldoc header - remove RingBuffer.c to us in-kernel ringbuffer functions instead. - audit the vmbus to verify it is working properly with the driver model + - convert vmbus driver interface function pointer tables + to constant, a.k.a vmbus_ops - see if the vmbus can be merged with the other virtual busses in the kernel - audit the network driver + - use existing net_device_stats struct in network device + - checking for carrier inside open is wrong, network device API + confusion?? - audit the block driver - audit the scsi driver diff --git a/drivers/staging/hv/osd.h b/drivers/staging/hv/osd.h index 9504604c72bd..ce064e8ea644 100644 --- a/drivers/staging/hv/osd.h +++ b/drivers/staging/hv/osd.h @@ -25,6 +25,7 @@ #ifndef _OSD_H_ #define _OSD_H_ +#include <linux/workqueue.h> /* Defines */ #define ALIGN_UP(value, align) (((value) & (align-1)) ? \ diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index 582318f10222..894eecfc63ca 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -507,12 +507,12 @@ static struct hv_device *vmbus_child_device_create(struct hv_guid *type, child_device_obj = &child_device_ctx->device_obj; child_device_obj->context = context; - memcpy(&child_device_obj->deviceType, &type, sizeof(struct hv_guid)); - memcpy(&child_device_obj->deviceInstance, &instance, + memcpy(&child_device_obj->deviceType, type, sizeof(struct hv_guid)); + memcpy(&child_device_obj->deviceInstance, instance, sizeof(struct hv_guid)); - memcpy(&child_device_ctx->class_id, &type, sizeof(struct hv_guid)); - memcpy(&child_device_ctx->device_id, &instance, sizeof(struct hv_guid)); + memcpy(&child_device_ctx->class_id, type, sizeof(struct hv_guid)); + memcpy(&child_device_ctx->device_id, instance, sizeof(struct hv_guid)); DPRINT_EXIT(VMBUS_DRV); @@ -537,18 +537,7 @@ static int vmbus_child_device_register(struct hv_device *root_device_obj, DPRINT_DBG(VMBUS_DRV, "child device (%p) registering", child_device_ctx); - /* Make sure we are not registered already */ - if (strlen(dev_name(&child_device_ctx->device)) != 0) { - DPRINT_ERR(VMBUS_DRV, - "child device (%p) already registered - busid %s", - child_device_ctx, - dev_name(&child_device_ctx->device)); - - ret = -1; - goto Cleanup; - } - - /* Set the device bus id. Otherwise, device_register()will fail. */ + /* Set the device name. Otherwise, device_register() will fail. */ dev_set_name(&child_device_ctx->device, "vmbus_0_%d", atomic_inc_return(&device_num)); @@ -573,7 +562,6 @@ static int vmbus_child_device_register(struct hv_device *root_device_obj, DPRINT_INFO(VMBUS_DRV, "child device (%p) registered", &child_device_ctx->device); -Cleanup: DPRINT_EXIT(VMBUS_DRV); return ret; @@ -623,8 +611,6 @@ static void vmbus_child_device_destroy(struct hv_device *device_obj) static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env) { struct device_context *device_ctx = device_to_device_context(device); - int i = 0; - int len = 0; int ret; DPRINT_ENTER(VMBUS_DRV); @@ -644,8 +630,6 @@ static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env) device_ctx->class_id.data[14], device_ctx->class_id.data[15]); - env->envp_idx = i; - env->buflen = len; ret = add_uevent_var(env, "VMBUS_DEVICE_CLASS_GUID={" "%02x%02x%02x%02x-%02x%02x-%02x%02x-" "%02x%02x%02x%02x%02x%02x%02x%02x}", @@ -691,8 +675,6 @@ static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env) if (ret) return ret; - env->envp[env->envp_idx] = NULL; - DPRINT_EXIT(VMBUS_DRV); return 0; diff --git a/drivers/staging/otus/Kconfig b/drivers/staging/otus/Kconfig index d549d08fd495..f6cc2625e341 100644 --- a/drivers/staging/otus/Kconfig +++ b/drivers/staging/otus/Kconfig @@ -1,6 +1,6 @@ config OTUS tristate "Atheros OTUS 802.11n USB wireless support" - depends on USB && WLAN_80211 && MAC80211 + depends on USB && WLAN && MAC80211 default N ---help--- Enable support for Atheros 802.11n USB hardware: diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index dd7d3fde9699..4ce399b6d237 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -2071,11 +2071,15 @@ static void panel_detach(struct parport *port) return; } - if (keypad_enabled && keypad_initialized) + if (keypad_enabled && keypad_initialized) { misc_deregister(&keypad_dev); + keypad_initialized = 0; + } - if (lcd_enabled && lcd_initialized) + if (lcd_enabled && lcd_initialized) { misc_deregister(&lcd_dev); + lcd_initialized = 0; + } parport_release(pprt); parport_unregister_device(pprt); @@ -2211,13 +2215,16 @@ static void __exit panel_cleanup_module(void) del_timer(&scan_timer); if (pprt != NULL) { - if (keypad_enabled) + if (keypad_enabled) { misc_deregister(&keypad_dev); + keypad_initialized = 0; + } if (lcd_enabled) { panel_lcd_print("\x0cLCD driver " PANEL_VERSION "\nunloaded.\x1b[Lc\x1b[Lb\x1b[L-"); misc_deregister(&lcd_dev); + lcd_initialized = 0; } /* TODO: free all input signals */ diff --git a/drivers/staging/rt2860/Kconfig b/drivers/staging/rt2860/Kconfig index 7f44e5e72463..efe38e25c5ed 100644 --- a/drivers/staging/rt2860/Kconfig +++ b/drivers/staging/rt2860/Kconfig @@ -1,5 +1,5 @@ config RT2860 tristate "Ralink 2860 wireless support" - depends on PCI && X86 && WLAN_80211 + depends on PCI && X86 && WLAN ---help--- This is an experimental driver for the Ralink 2860 wireless chip. diff --git a/drivers/staging/rt2870/Kconfig b/drivers/staging/rt2870/Kconfig index 76841f6dea93..aea5c8221810 100644 --- a/drivers/staging/rt2870/Kconfig +++ b/drivers/staging/rt2870/Kconfig @@ -1,5 +1,5 @@ config RT2870 tristate "Ralink 2870/3070 wireless support" - depends on USB && X86 && WLAN_80211 + depends on USB && X86 && WLAN ---help--- This is an experimental driver for the Ralink xx70 wireless chips. diff --git a/drivers/staging/rt3090/Kconfig b/drivers/staging/rt3090/Kconfig index 255e8eaa4836..2b3f745d72b7 100644 --- a/drivers/staging/rt3090/Kconfig +++ b/drivers/staging/rt3090/Kconfig @@ -1,5 +1,5 @@ config RT3090 tristate "Ralink 3090 wireless support" - depends on PCI && X86 && WLAN_80211 + depends on PCI && X86 && WLAN ---help--- This is an experimental driver for the Ralink 3090 wireless chip. diff --git a/drivers/staging/rtl8187se/Kconfig b/drivers/staging/rtl8187se/Kconfig index 236e42725447..203c79b8180f 100644 --- a/drivers/staging/rtl8187se/Kconfig +++ b/drivers/staging/rtl8187se/Kconfig @@ -1,6 +1,6 @@ config RTL8187SE tristate "RealTek RTL8187SE Wireless LAN NIC driver" - depends on PCI + depends on PCI && WLAN depends on WIRELESS_EXT default N ---help--- diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c index 013c3e19ae25..4c5d63fd5833 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c @@ -53,10 +53,8 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, list_del(ptr); - if (entry->ops) { + if (entry->ops) entry->ops->deinit(entry->priv); - module_put(entry->ops->owner); - } kfree(entry); } } diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c index 6fbe4890cb66..18392fce487d 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c @@ -189,10 +189,8 @@ void free_ieee80211(struct net_device *dev) for (i = 0; i < WEP_KEYS; i++) { struct ieee80211_crypt_data *crypt = ieee->crypt[i]; if (crypt) { - if (crypt->ops) { + if (crypt->ops) crypt->ops->deinit(crypt->priv); - module_put(crypt->ops->owner); - } kfree(crypt); ieee->crypt[i] = NULL; } diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c index 59b2ab48cdcf..334e4c7ec61b 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c @@ -2839,16 +2839,12 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee, goto skip_host_crypt; ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) { - request_module("ieee80211_crypt_wep"); + if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) { - request_module("ieee80211_crypt_tkip"); + else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) { - request_module("ieee80211_crypt_ccmp"); + else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - } if (ops == NULL) { printk("unknown crypto alg '%s'\n", param->u.crypt.alg); param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG; @@ -2869,7 +2865,7 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee, } memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data)); new_crypt->ops = ops; - if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) + if (new_crypt->ops) new_crypt->priv = new_crypt->ops->init(param->u.crypt.idx); diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c index 8d8bdd0a130e..a08b97a09512 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c @@ -331,12 +331,10 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee, return -ENOMEM; memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data)); new_crypt->ops = ieee80211_get_crypto_ops("WEP"); - if (!new_crypt->ops) { - request_module("ieee80211_crypt_wep"); + if (!new_crypt->ops) new_crypt->ops = ieee80211_get_crypto_ops("WEP"); - } - if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) + if (new_crypt->ops) new_crypt->priv = new_crypt->ops->init(key); if (!new_crypt->ops || !new_crypt->priv) { @@ -483,7 +481,7 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; int i, idx, ret = 0; int group_key = 0; - const char *alg, *module; + const char *alg; struct ieee80211_crypto_ops *ops; struct ieee80211_crypt_data **crypt; @@ -539,15 +537,12 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, switch (ext->alg) { case IW_ENCODE_ALG_WEP: alg = "WEP"; - module = "ieee80211_crypt_wep"; break; case IW_ENCODE_ALG_TKIP: alg = "TKIP"; - module = "ieee80211_crypt_tkip"; break; case IW_ENCODE_ALG_CCMP: alg = "CCMP"; - module = "ieee80211_crypt_ccmp"; break; default: IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n", @@ -558,10 +553,8 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, // printk("8-09-08-9=====>%s, alg name:%s\n",__func__, alg); ops = ieee80211_get_crypto_ops(alg); - if (ops == NULL) { - request_module(module); + if (ops == NULL) ops = ieee80211_get_crypto_ops(alg); - } if (ops == NULL) { IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n", dev->name, ext->alg); @@ -581,7 +574,7 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, goto done; } new_crypt->ops = ops; - if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) + if (new_crypt->ops) new_crypt->priv = new_crypt->ops->init(idx); if (new_crypt->priv == NULL) { kfree(new_crypt); diff --git a/drivers/staging/rtl8192e/Kconfig b/drivers/staging/rtl8192e/Kconfig index 3100aa58c940..37e4fde45073 100644 --- a/drivers/staging/rtl8192e/Kconfig +++ b/drivers/staging/rtl8192e/Kconfig @@ -1,6 +1,6 @@ config RTL8192E tristate "RealTek RTL8192E Wireless LAN NIC driver" - depends on PCI + depends on PCI && WLAN depends on WIRELESS_EXT default N ---help--- diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c index 1a8ea8a40c3c..b1c54932da3e 100644 --- a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c +++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c @@ -53,14 +53,8 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, list_del(ptr); - if (entry->ops) { + if (entry->ops) entry->ops->deinit(entry->priv); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - module_put(entry->ops->owner); -#else - __MOD_DEC_USE_COUNT(entry->ops->owner); -#endif - } kfree(entry); } } diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c index 16256a31f993..12c2a18e1fa2 100644 --- a/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c +++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c @@ -242,14 +242,8 @@ void free_ieee80211(struct net_device *dev) for (i = 0; i < WEP_KEYS; i++) { struct ieee80211_crypt_data *crypt = ieee->crypt[i]; if (crypt) { - if (crypt->ops) { + if (crypt->ops) crypt->ops->deinit(crypt->priv); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - module_put(crypt->ops->owner); -#else - __MOD_DEC_USE_COUNT(crypt->ops->owner); -#endif - } kfree(crypt); ieee->crypt[i] = NULL; } diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c index 2fc04df872ca..eae7c4579a68 100644 --- a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c @@ -3284,17 +3284,14 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee, goto skip_host_crypt; ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) { - request_module("ieee80211_crypt_wep"); + if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - //set WEP40 first, it will be modified according to WEP104 or WEP40 at other place - } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) { - request_module("ieee80211_crypt_tkip"); + /* set WEP40 first, it will be modified according to WEP104 or + * WEP40 at other place */ + else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) { - request_module("ieee80211_crypt_ccmp"); + else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - } if (ops == NULL) { printk("unknown crypto alg '%s'\n", param->u.crypt.alg); param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG; @@ -3315,11 +3312,7 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee, } memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data)); new_crypt->ops = ops; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) -#else - if (new_crypt->ops && try_inc_mod_count(new_crypt->ops->owner)) -#endif + if (new_crypt->ops) new_crypt->priv = new_crypt->ops->init(param->u.crypt.idx); diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c index 223483126b0e..4e34a1f4c66b 100644 --- a/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c +++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c @@ -482,15 +482,9 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee, return -ENOMEM; memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data)); new_crypt->ops = ieee80211_get_crypto_ops("WEP"); - if (!new_crypt->ops) { - request_module("ieee80211_crypt_wep"); + if (!new_crypt->ops) new_crypt->ops = ieee80211_get_crypto_ops("WEP"); - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) -#else - if (new_crypt->ops && try_inc_mod_count(new_crypt->ops->owner)) -#endif + if (new_crypt->ops) new_crypt->priv = new_crypt->ops->init(key); if (!new_crypt->ops || !new_crypt->priv) { @@ -644,7 +638,7 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; int i, idx; int group_key = 0; - const char *alg, *module; + const char *alg; struct ieee80211_crypto_ops *ops; struct ieee80211_crypt_data **crypt; @@ -711,15 +705,12 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, switch (ext->alg) { case IW_ENCODE_ALG_WEP: alg = "WEP"; - module = "ieee80211_crypt_wep"; break; case IW_ENCODE_ALG_TKIP: alg = "TKIP"; - module = "ieee80211_crypt_tkip"; break; case IW_ENCODE_ALG_CCMP: alg = "CCMP"; - module = "ieee80211_crypt_ccmp"; break; default: IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n", @@ -730,10 +721,8 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, printk("alg name:%s\n",alg); ops = ieee80211_get_crypto_ops(alg); - if (ops == NULL) { - request_module(module); + if (ops == NULL) ops = ieee80211_get_crypto_ops(alg); - } if (ops == NULL) { IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n", dev->name, ext->alg); @@ -758,7 +747,7 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, goto done; } new_crypt->ops = ops; - if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) + if (new_crypt->ops) new_crypt->priv = new_crypt->ops->init(idx); if (new_crypt->priv == NULL) { kfree(new_crypt); diff --git a/drivers/staging/rtl8192su/Kconfig b/drivers/staging/rtl8192su/Kconfig index 770f41280f21..b8c95f942069 100644 --- a/drivers/staging/rtl8192su/Kconfig +++ b/drivers/staging/rtl8192su/Kconfig @@ -1,6 +1,6 @@ config RTL8192SU tristate "RealTek RTL8192SU Wireless LAN NIC driver" - depends on PCI + depends on PCI && WLAN depends on WIRELESS_EXT default N ---help--- diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt.c index d76a54d59d2f..521e7b989934 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt.c +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt.c @@ -53,10 +53,8 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, list_del(ptr); - if (entry->ops) { + if (entry->ops) entry->ops->deinit(entry->priv); - module_put(entry->ops->owner); - } kfree(entry); } } diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c index 68dc8fa094cc..c3383bb8b760 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c @@ -216,10 +216,8 @@ void free_ieee80211(struct net_device *dev) for (i = 0; i < WEP_KEYS; i++) { struct ieee80211_crypt_data *crypt = ieee->crypt[i]; if (crypt) { - if (crypt->ops) { + if (crypt->ops) crypt->ops->deinit(crypt->priv); - module_put(crypt->ops->owner); - } kfree(crypt); ieee->crypt[i] = NULL; } diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c index c64ae03f68a0..fd8e11252f1b 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c @@ -3026,17 +3026,14 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee, goto skip_host_crypt; ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) { - request_module("ieee80211_crypt_wep"); + if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - //set WEP40 first, it will be modified according to WEP104 or WEP40 at other place - } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) { - request_module("ieee80211_crypt_tkip"); + /* set WEP40 first, it will be modified according to WEP104 or + * WEP40 at other place */ + else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) { - request_module("ieee80211_crypt_ccmp"); + else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - } if (ops == NULL) { printk("unknown crypto alg '%s'\n", param->u.crypt.alg); param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG; @@ -3058,7 +3055,7 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee, memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data)); new_crypt->ops = ops; - if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) + if (new_crypt->ops) new_crypt->priv = new_crypt->ops->init(param->u.crypt.idx); diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c index 107759024335..6146c6435dde 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c @@ -358,11 +358,9 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee, return -ENOMEM; memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data)); new_crypt->ops = ieee80211_get_crypto_ops("WEP"); - if (!new_crypt->ops) { - request_module("ieee80211_crypt_wep"); + if (!new_crypt->ops) new_crypt->ops = ieee80211_get_crypto_ops("WEP"); - } - if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) + if (new_crypt->ops) new_crypt->priv = new_crypt->ops->init(key); if (!new_crypt->ops || !new_crypt->priv) { @@ -507,7 +505,7 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; int i, idx; int group_key = 0; - const char *alg, *module; + const char *alg; struct ieee80211_crypto_ops *ops; struct ieee80211_crypt_data **crypt; @@ -570,15 +568,12 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, switch (ext->alg) { case IW_ENCODE_ALG_WEP: alg = "WEP"; - module = "ieee80211_crypt_wep"; break; case IW_ENCODE_ALG_TKIP: alg = "TKIP"; - module = "ieee80211_crypt_tkip"; break; case IW_ENCODE_ALG_CCMP: alg = "CCMP"; - module = "ieee80211_crypt_ccmp"; break; default: IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n", @@ -589,10 +584,8 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, printk("alg name:%s\n",alg); ops = ieee80211_get_crypto_ops(alg); - if (ops == NULL) { - request_module("%s", module); + if (ops == NULL) ops = ieee80211_get_crypto_ops(alg); - } if (ops == NULL) { IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n", dev->name, ext->alg); @@ -612,7 +605,7 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, goto done; } new_crypt->ops = ops; - if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) + if (new_crypt->ops) new_crypt->priv = new_crypt->ops->init(idx); if (new_crypt->priv == NULL) { kfree(new_crypt); diff --git a/drivers/staging/stlc45xx/Kconfig b/drivers/staging/stlc45xx/Kconfig deleted file mode 100644 index 947fb75a9c68..000000000000 --- a/drivers/staging/stlc45xx/Kconfig +++ /dev/null @@ -1,8 +0,0 @@ -config STLC45XX - tristate "stlc4550/4560 support" - depends on MAC80211 && WLAN_80211 && SPI_MASTER && GENERIC_HARDIRQS - ---help--- - This is a driver for stlc4550 and stlc4560 chipsets. - - To compile this driver as a module, choose M here: the module will be - called stlc45xx. If unsure, say N. diff --git a/drivers/staging/stlc45xx/Makefile b/drivers/staging/stlc45xx/Makefile deleted file mode 100644 index 7ee32903055a..000000000000 --- a/drivers/staging/stlc45xx/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_STLC45XX) += stlc45xx.o diff --git a/drivers/staging/stlc45xx/stlc45xx.c b/drivers/staging/stlc45xx/stlc45xx.c deleted file mode 100644 index be99eb33d817..000000000000 --- a/drivers/staging/stlc45xx/stlc45xx.c +++ /dev/null @@ -1,2594 +0,0 @@ -/* - * This file is part of stlc45xx - * - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: Kalle Valo <kalle.valo@nokia.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include "stlc45xx.h" - -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/interrupt.h> -#include <linux/firmware.h> -#include <linux/delay.h> -#include <linux/irq.h> -#include <linux/spi/spi.h> -#include <linux/etherdevice.h> -#include <linux/gpio.h> -#include <linux/moduleparam.h> - -#include "stlc45xx_lmac.h" - -/* - * gpios should be handled in board files and provided via platform data, - * but because it's currently impossible for stlc45xx to have a header file - * in include/linux, let's use module paramaters for now - */ -static int stlc45xx_gpio_power = 97; -module_param(stlc45xx_gpio_power, int, 0444); -MODULE_PARM_DESC(stlc45xx_gpio_power, "stlc45xx gpio number for power line"); - -static int stlc45xx_gpio_irq = 87; -module_param(stlc45xx_gpio_irq, int, 0444); -MODULE_PARM_DESC(stlc45xx_gpio_irq, "stlc45xx gpio number for irq line"); - -static const u8 default_cal_channels[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x09, - 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, - 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xe0, 0x00, 0xe0, 0x00, - 0xe0, 0x00, 0xe0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, - 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, - 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, - 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, - 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, - 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, - 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, - 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, - 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, - 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, - 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, - 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, - 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, - 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, - 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, - 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, - 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x71, 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, - 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, - 0x10, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, - 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, - 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, - 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, - 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, - 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, - 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, - 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, - 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, - 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, - 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, - 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, - 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, - 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, - 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, - 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, - 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, - 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, - 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xf0, 0x00, 0xf0, - 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, - 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, - 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, - 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, - 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, - 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, - 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, - 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, - 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, - 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, - 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, - 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, - 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, - 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, - 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, - 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, - 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x09, 0x00, 0x00, 0xc9, 0xff, - 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, - 0x01, 0x10, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, - 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, - 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, - 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, - 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, - 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, - 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, - 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, - 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, - 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, - 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, - 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, - 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, - 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, - 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, - 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, - 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, - 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xf0, 0x00, - 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, - 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, - 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, - 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, - 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, - 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, - 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, - 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, - 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, - 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, - 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, - 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, - 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, - 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, - 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, - 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, - 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x09, 0x00, 0x00, 0xc9, - 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, - 0x10, 0x01, 0x10, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, - 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, - 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, - 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, - 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, - 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, - 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, - 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, - 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, - 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, - 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, - 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, - 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, - 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, - 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, - 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, - 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, - 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, - 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x8a, 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, - 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xf0, - 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00, - 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, - 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, - 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, - 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, - 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, - 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, - 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, - 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, - 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, - 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, - 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, - 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, - 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, - 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, - 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, - 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x09, 0x00, 0x00, - 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, - 0x01, 0x10, 0x01, 0x10, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, - 0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, - 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, - 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, - 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, - 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, - 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, - 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, - 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, - 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, - 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, - 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, - 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, - 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, - 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, - 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, - 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, - 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x06, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x94, 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, - 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, - 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0, - 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, - 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, - 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, - 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, - 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, - 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, - 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, - 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, - 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, - 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, - 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, - 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, - 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, - 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, - 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, - 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x09, 0x00, - 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, - 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, - 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, - 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, - 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, - 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, - 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, - 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, - 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, - 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, - 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, - 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, - 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, - 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, - 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, - 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, - 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, - 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, - 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x06, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x9e, 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, - 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, - 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, 0x00, - 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, - 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, - 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, - 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, - 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, - 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, - 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, - 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, - 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, - 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, - 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, - 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, - 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, - 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, - 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, - 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 }; - -static const u8 default_cal_rssi[] = { - 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, - 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, - 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, - 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, - 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, - 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, - 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, - 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00 }; - -static void stlc45xx_tx_edcf(struct stlc45xx *stlc); -static void stlc45xx_tx_setup(struct stlc45xx *stlc); -static void stlc45xx_tx_scan(struct stlc45xx *stlc); -static void stlc45xx_tx_psm(struct stlc45xx *stlc, bool enable); -static int stlc45xx_tx_nullfunc(struct stlc45xx *stlc, bool powersave); -static int stlc45xx_tx_pspoll(struct stlc45xx *stlc, bool powersave); - -static ssize_t stlc45xx_sysfs_show_cal_rssi(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct stlc45xx *stlc = dev_get_drvdata(dev); - ssize_t len; - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - len = PAGE_SIZE; - - mutex_lock(&stlc->mutex); - - if (stlc->cal_rssi) - hex_dump_to_buffer(stlc->cal_rssi, RSSI_CAL_ARRAY_LEN, 16, - 2, buf, len, 0); - mutex_unlock(&stlc->mutex); - - len = strlen(buf); - - return len; -} - -static ssize_t stlc45xx_sysfs_store_cal_rssi(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct stlc45xx *stlc = dev_get_drvdata(dev); - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - mutex_lock(&stlc->mutex); - - if (count != RSSI_CAL_ARRAY_LEN) { - stlc45xx_error("invalid cal_rssi length: %zu", count); - count = 0; - goto out_unlock; - } - - kfree(stlc->cal_rssi); - - stlc->cal_rssi = kmemdup(buf, RSSI_CAL_ARRAY_LEN, GFP_KERNEL); - - if (!stlc->cal_rssi) { - stlc45xx_error("failed to allocate memory for cal_rssi"); - count = 0; - goto out_unlock; - } - - out_unlock: - mutex_unlock(&stlc->mutex); - - return count; -} - -static ssize_t stlc45xx_sysfs_show_cal_channels(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct stlc45xx *stlc = dev_get_drvdata(dev); - ssize_t len; - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - len = PAGE_SIZE; - - mutex_lock(&stlc->mutex); - - if (stlc->cal_channels) - hex_dump_to_buffer(stlc->cal_channels, CHANNEL_CAL_ARRAY_LEN, - 16, 2, buf, len, 0); - - mutex_unlock(&stlc->mutex); - - len = strlen(buf); - - return len; -} - -static ssize_t stlc45xx_sysfs_store_cal_channels(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct stlc45xx *stlc = dev_get_drvdata(dev); - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - mutex_lock(&stlc->mutex); - - if (count != CHANNEL_CAL_ARRAY_LEN) { - stlc45xx_error("invalid cal_channels size: %zu ", count); - count = 0; - goto out_unlock; - } - - kfree(stlc->cal_channels); - - stlc->cal_channels = kmemdup(buf, count, GFP_KERNEL); - - if (!stlc->cal_channels) { - stlc45xx_error("failed to allocate memory for cal_channels"); - count = 0; - goto out_unlock; - } - -out_unlock: - mutex_unlock(&stlc->mutex); - - return count; -} - -static ssize_t stlc45xx_sysfs_show_tx_buf(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct stlc45xx *stlc = dev_get_drvdata(dev); - struct txbuffer *entry; - ssize_t len = 0; - - stlc45xx_debug(DEBUG_FUNC, "%s()", __func__); - - mutex_lock(&stlc->mutex); - - list_for_each_entry(entry, &stlc->tx_sent, tx_list) { - len += sprintf(buf + len, "0x%x: 0x%x-0x%x\n", - entry->handle, entry->start, - entry->end); - } - - mutex_unlock(&stlc->mutex); - - return len; -} - -static DEVICE_ATTR(cal_rssi, S_IRUGO | S_IWUSR, - stlc45xx_sysfs_show_cal_rssi, - stlc45xx_sysfs_store_cal_rssi); -static DEVICE_ATTR(cal_channels, S_IRUGO | S_IWUSR, - stlc45xx_sysfs_show_cal_channels, - stlc45xx_sysfs_store_cal_channels); -static DEVICE_ATTR(tx_buf, S_IRUGO, stlc45xx_sysfs_show_tx_buf, NULL); - -static void stlc45xx_spi_read(struct stlc45xx *stlc, unsigned long addr, - void *buf, size_t len) -{ - struct spi_transfer t[2]; - struct spi_message m; - - /* We first push the address */ - addr = (addr << 8) | ADDR_READ_BIT_15; - - spi_message_init(&m); - memset(t, 0, sizeof(t)); - - t[0].tx_buf = &addr; - t[0].len = 2; - spi_message_add_tail(&t[0], &m); - - t[1].rx_buf = buf; - t[1].len = len; - spi_message_add_tail(&t[1], &m); - - spi_sync(stlc->spi, &m); -} - - -static void stlc45xx_spi_write(struct stlc45xx *stlc, unsigned long addr, - void *buf, size_t len) -{ - struct spi_transfer t[3]; - struct spi_message m; - u16 last_word; - - /* We first push the address */ - addr = addr << 8; - - spi_message_init(&m); - memset(t, 0, sizeof(t)); - - t[0].tx_buf = &addr; - t[0].len = 2; - spi_message_add_tail(&t[0], &m); - - t[1].tx_buf = buf; - t[1].len = len; - spi_message_add_tail(&t[1], &m); - - if (len % 2) { - last_word = ((u8 *)buf)[len - 1]; - - t[2].tx_buf = &last_word; - t[2].len = 2; - spi_message_add_tail(&t[2], &m); - } - - spi_sync(stlc->spi, &m); -} - -static u16 stlc45xx_read16(struct stlc45xx *stlc, unsigned long addr) -{ - u16 val; - - stlc45xx_spi_read(stlc, addr, &val, sizeof(val)); - - return val; -} - -static u32 stlc45xx_read32(struct stlc45xx *stlc, unsigned long addr) -{ - u32 val; - - stlc45xx_spi_read(stlc, addr, &val, sizeof(val)); - - return val; -} - -static void stlc45xx_write16(struct stlc45xx *stlc, unsigned long addr, u16 val) -{ - stlc45xx_spi_write(stlc, addr, &val, sizeof(val)); -} - -static void stlc45xx_write32(struct stlc45xx *stlc, unsigned long addr, u32 val) -{ - stlc45xx_spi_write(stlc, addr, &val, sizeof(val)); -} - -struct stlc45xx_spi_reg { - u16 address; - u16 length; - char *name; -}; - -/* caller must hold tx_lock */ -static void stlc45xx_txbuffer_dump(struct stlc45xx *stlc) -{ - struct txbuffer *txbuffer; - char *buf, *pos; - int buf_len, l, count; - - if (!(DEBUG_LEVEL & DEBUG_TXBUFFER)) - return; - - stlc45xx_debug(DEBUG_FUNC, "%s()", __func__); - - buf_len = 500; - buf = kmalloc(buf_len, GFP_ATOMIC); - if (!buf) - return; - - pos = buf; - count = 0; - - list_for_each_entry(txbuffer, &stlc->txbuffer, buffer_list) { - l = snprintf(pos, buf_len, "0x%x-0x%x,", - txbuffer->start, txbuffer->end); - /* drop the null byte */ - pos += l; - buf_len -= l; - count++; - } - - if (count == 0) - *pos = '\0'; - else - *--pos = '\0'; - - stlc45xx_debug(DEBUG_TXBUFFER, "txbuffer: in buffer %d regions: %s", - count, buf); - - kfree(buf); -} - -/* caller must hold tx_lock */ -static int stlc45xx_txbuffer_find(struct stlc45xx *stlc, size_t len) -{ - struct txbuffer *txbuffer; - int pos; - - stlc45xx_debug(DEBUG_FUNC, "%s()", __func__); - - pos = FIRMWARE_TXBUFFER_START; - - if (list_empty(&stlc->txbuffer)) - goto out; - - /* - * the entries in txbuffer must be in the same order as they are in - * the real buffer - */ - list_for_each_entry(txbuffer, &stlc->txbuffer, buffer_list) { - if (pos + len < txbuffer->start) - break; - pos = ALIGN(txbuffer->end + 1, 4); - } - - if (pos + len > FIRMWARE_TXBUFFER_END) - /* not enough room */ - pos = -1; - - stlc45xx_debug(DEBUG_TXBUFFER, "txbuffer: find %zu B: 0x%x", len, pos); - -out: - return pos; -} - -static int stlc45xx_txbuffer_add(struct stlc45xx *stlc, - struct txbuffer *txbuffer) -{ - struct txbuffer *r, *prev = NULL; - - if (list_empty(&stlc->txbuffer)) { - list_add(&txbuffer->buffer_list, &stlc->txbuffer); - return 0; - } - - r = list_first_entry(&stlc->txbuffer, struct txbuffer, buffer_list); - - if (txbuffer->start < r->start) { - /* add to the beginning of the list */ - list_add(&txbuffer->buffer_list, &stlc->txbuffer); - return 0; - } - - prev = NULL; - list_for_each_entry(r, &stlc->txbuffer, buffer_list) { - /* skip first entry, we checked for that above */ - if (!prev) { - prev = r; - continue; - } - - /* double-check overlaps */ - WARN_ON_ONCE(txbuffer->start >= r->start && - txbuffer->start <= r->end); - WARN_ON_ONCE(txbuffer->end >= r->start && - txbuffer->end <= r->end); - - if (prev->end < txbuffer->start && - txbuffer->end < r->start) { - /* insert at this spot */ - list_add_tail(&txbuffer->buffer_list, &r->buffer_list); - return 0; - } - - prev = r; - } - - /* not found */ - list_add_tail(&txbuffer->buffer_list, &stlc->txbuffer); - - return 0; - -} - -/* caller must hold tx_lock */ -static struct txbuffer *stlc45xx_txbuffer_alloc(struct stlc45xx *stlc, - size_t frame_len) -{ - struct txbuffer *entry = NULL; - size_t len; - int pos; - - stlc45xx_debug(DEBUG_FUNC, "%s()", __func__); - - len = FIRMWARE_TXBUFFER_HEADER + frame_len + FIRMWARE_TXBUFFER_TRAILER; - pos = stlc45xx_txbuffer_find(stlc, len); - - if (pos < 0) - return NULL; - - WARN_ON_ONCE(pos + len > FIRMWARE_TXBUFFER_END); - WARN_ON_ONCE(pos < FIRMWARE_TXBUFFER_START); - - entry = kmalloc(sizeof(*entry), GFP_ATOMIC); - entry->start = pos; - entry->frame_start = pos + FIRMWARE_TXBUFFER_HEADER; - entry->end = entry->start + len - 1; - - stlc45xx_debug(DEBUG_TXBUFFER, "txbuffer: allocated 0x%x-0x%x", - entry->start, entry->end); - - stlc45xx_txbuffer_add(stlc, entry); - - stlc45xx_txbuffer_dump(stlc); - - return entry; -} - -/* caller must hold tx_lock */ -static void stlc45xx_txbuffer_free(struct stlc45xx *stlc, - struct txbuffer *txbuffer) -{ - stlc45xx_debug(DEBUG_FUNC, "%s()", __func__); - - stlc45xx_debug(DEBUG_TXBUFFER, "txbuffer: freed 0x%x-0x%x", - txbuffer->start, txbuffer->end); - - list_del(&txbuffer->buffer_list); - kfree(txbuffer); -} - - -static int stlc45xx_wait_bit(struct stlc45xx *stlc, u16 reg, u32 mask, - u32 expected) -{ - int i; - char buffer[4]; - - for (i = 0; i < 2000; i++) { - stlc45xx_spi_read(stlc, reg, buffer, sizeof(buffer)); - if (((*(u32 *)buffer) & mask) == expected) - return 1; - msleep(1); - } - - return 0; -} - -static int stlc45xx_request_firmware(struct stlc45xx *stlc) -{ - const struct firmware *fw; - int ret; - - /* FIXME: should driver use it's own struct device? */ - ret = request_firmware(&fw, "3826.arm", &stlc->spi->dev); - - if (ret < 0) { - stlc45xx_error("request_firmware() failed: %d", ret); - return ret; - } - - if (fw->size % 4) { - stlc45xx_error("firmware size is not multiple of 32bit: %zu", - fw->size); - return -EILSEQ; /* Illegal byte sequence */; - } - - if (fw->size < 1000) { - stlc45xx_error("firmware is too small: %zu", fw->size); - return -EILSEQ; - } - - stlc->fw = kmemdup(fw->data, fw->size, GFP_KERNEL); - if (!stlc->fw) { - stlc45xx_error("could not allocate memory for firmware"); - return -ENOMEM; - } - - stlc->fw_len = fw->size; - - release_firmware(fw); - - return 0; -} - -static int stlc45xx_upload_firmware(struct stlc45xx *stlc) -{ - struct s_dma_regs dma_regs; - unsigned long fw_len, fw_addr; - long _fw_len; - int ret; - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - if (!stlc->fw) { - ret = stlc45xx_request_firmware(stlc); - if (ret < 0) - return ret; - } - - /* stop the device */ - stlc45xx_write16(stlc, SPI_ADRS_DEV_CTRL_STAT, - SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_HOST_RESET - | SPI_CTRL_STAT_START_HALTED); - - msleep(TARGET_BOOT_SLEEP); - - stlc45xx_write16(stlc, SPI_ADRS_DEV_CTRL_STAT, - SPI_CTRL_STAT_HOST_OVERRIDE - | SPI_CTRL_STAT_START_HALTED); - - msleep(TARGET_BOOT_SLEEP); - - fw_addr = FIRMWARE_ADDRESS; - fw_len = stlc->fw_len; - - while (fw_len > 0) { - _fw_len = (fw_len > SPI_MAX_PACKET_SIZE) - ? SPI_MAX_PACKET_SIZE : fw_len; - dma_regs.cmd = SPI_DMA_WRITE_CTRL_ENABLE; - dma_regs.len = cpu_to_le16(_fw_len); - dma_regs.addr = cpu_to_le32(fw_addr); - - fw_len -= _fw_len; - fw_addr += _fw_len; - - stlc45xx_write16(stlc, SPI_ADRS_DMA_WRITE_CTRL, dma_regs.cmd); - - if (stlc45xx_wait_bit(stlc, SPI_ADRS_DMA_WRITE_CTRL, - HOST_ALLOWED, HOST_ALLOWED) == 0) { - stlc45xx_error("fw_upload not allowed to DMA write"); - return -EAGAIN; - } - - stlc45xx_write16(stlc, SPI_ADRS_DMA_WRITE_LEN, dma_regs.len); - stlc45xx_write32(stlc, SPI_ADRS_DMA_WRITE_BASE, dma_regs.addr); - - stlc45xx_spi_write(stlc, SPI_ADRS_DMA_DATA, stlc->fw, _fw_len); - - /* FIXME: I think this doesn't work if firmware is large, - * this loop goes to second round. fw->data is not - * increased at all! */ - } - - BUG_ON(fw_len != 0); - - /* enable host interrupts */ - stlc45xx_write32(stlc, SPI_ADRS_HOST_INT_EN, SPI_HOST_INTS_DEFAULT); - - /* boot the device */ - stlc45xx_write16(stlc, SPI_ADRS_DEV_CTRL_STAT, - SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_HOST_RESET - | SPI_CTRL_STAT_RAM_BOOT); - - msleep(TARGET_BOOT_SLEEP); - - stlc45xx_write16(stlc, SPI_ADRS_DEV_CTRL_STAT, - SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_RAM_BOOT); - msleep(TARGET_BOOT_SLEEP); - - return 0; -} - -/* caller must hold tx_lock */ -static void stlc45xx_check_txsent(struct stlc45xx *stlc) -{ - struct txbuffer *entry, *n; - - list_for_each_entry_safe(entry, n, &stlc->tx_sent, tx_list) { - if (time_after(jiffies, entry->lifetime)) { - if (net_ratelimit()) - stlc45xx_warning("frame 0x%x lifetime exceeded", - entry->start); - list_del(&entry->tx_list); - skb_pull(entry->skb, entry->header_len); - ieee80211_tx_status(stlc->hw, entry->skb); - stlc45xx_txbuffer_free(stlc, entry); - } - } -} - -static void stlc45xx_power_off(struct stlc45xx *stlc) -{ - disable_irq(gpio_to_irq(stlc45xx_gpio_irq)); - gpio_set_value(stlc45xx_gpio_power, 0); -} - -static void stlc45xx_power_on(struct stlc45xx *stlc) -{ - gpio_set_value(stlc45xx_gpio_power, 1); - enable_irq(gpio_to_irq(stlc45xx_gpio_irq)); - - /* - * need to wait a while before device can be accessed, the length - * is just a guess - */ - msleep(10); -} - -/* caller must hold tx_lock */ -static void stlc45xx_flush_queues(struct stlc45xx *stlc) -{ - struct txbuffer *entry; - - while (!list_empty(&stlc->tx_sent)) { - entry = list_first_entry(&stlc->tx_sent, - struct txbuffer, tx_list); - list_del(&entry->tx_list); - dev_kfree_skb(entry->skb); - stlc45xx_txbuffer_free(stlc, entry); - } - - WARN_ON(!list_empty(&stlc->tx_sent)); - - while (!list_empty(&stlc->tx_pending)) { - entry = list_first_entry(&stlc->tx_pending, - struct txbuffer, tx_list); - list_del(&entry->tx_list); - dev_kfree_skb(entry->skb); - stlc45xx_txbuffer_free(stlc, entry); - } - - WARN_ON(!list_empty(&stlc->tx_pending)); - WARN_ON(!list_empty(&stlc->txbuffer)); -} - -static void stlc45xx_work_reset(struct work_struct *work) -{ - struct stlc45xx *stlc = container_of(work, struct stlc45xx, - work_reset); - - mutex_lock(&stlc->mutex); - - if (stlc->fw_state != FW_STATE_RESET) - goto out; - - stlc45xx_power_off(stlc); - - mutex_unlock(&stlc->mutex); - - /* wait that all work_structs have finished, we can't hold - * stlc->mutex to avoid deadlock */ - cancel_work_sync(&stlc->work); - - /* FIXME: find out good value to wait for chip power down */ - msleep(100); - - mutex_lock(&stlc->mutex); - - /* FIXME: we should gracefully handle if the state has changed - * after re-acquiring mutex */ - WARN_ON(stlc->fw_state != FW_STATE_RESET); - - spin_lock_bh(&stlc->tx_lock); - stlc45xx_flush_queues(stlc); - spin_unlock_bh(&stlc->tx_lock); - - stlc->fw_state = FW_STATE_RESETTING; - - stlc45xx_power_on(stlc); - stlc45xx_upload_firmware(stlc); - -out: - mutex_unlock(&stlc->mutex); -} - -/* caller must hold mutex */ -static void stlc45xx_reset(struct stlc45xx *stlc) -{ - stlc45xx_warning("resetting firmware"); - stlc->fw_state = FW_STATE_RESET; - ieee80211_stop_queues(stlc->hw); - queue_work(stlc->hw->workqueue, &stlc->work_reset); -} - -static void stlc45xx_work_tx_timeout(struct work_struct *work) -{ - struct stlc45xx *stlc = container_of(work, struct stlc45xx, - work_tx_timeout.work); - - stlc45xx_warning("tx timeout"); - - mutex_lock(&stlc->mutex); - - if (stlc->fw_state != FW_STATE_READY) - goto out; - - stlc45xx_reset(stlc); - -out: - mutex_unlock(&stlc->mutex); -} - -static void stlc45xx_int_ack(struct stlc45xx *stlc, u32 val) -{ - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - stlc45xx_write32(stlc, SPI_ADRS_HOST_INT_ACK, val); -} - -static void stlc45xx_wakeup(struct stlc45xx *stlc) -{ - unsigned long timeout; - u32 ints; - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - /* wake the chip */ - stlc45xx_write32(stlc, SPI_ADRS_ARM_INTERRUPTS, SPI_TARGET_INT_WAKEUP); - - /* And wait for the READY interrupt */ - timeout = jiffies + HZ; - - ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS); - while (!(ints & SPI_HOST_INT_READY)) { - if (time_after(jiffies, timeout)) - goto out; - ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS); - } - - stlc45xx_int_ack(stlc, SPI_HOST_INT_READY); - -out: - return; -} - -static void stlc45xx_sleep(struct stlc45xx *stlc) -{ - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - stlc45xx_write32(stlc, SPI_ADRS_ARM_INTERRUPTS, SPI_TARGET_INT_SLEEP); -} - -static void stlc45xx_int_ready(struct stlc45xx *stlc) -{ - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - stlc45xx_write32(stlc, SPI_ADRS_HOST_INT_EN, - SPI_HOST_INT_UPDATE | SPI_HOST_INT_SW_UPDATE); - - switch (stlc->fw_state) { - case FW_STATE_BOOTING: - stlc->fw_state = FW_STATE_READY; - complete(&stlc->fw_comp); - break; - case FW_STATE_RESETTING: - stlc->fw_state = FW_STATE_READY; - - stlc45xx_tx_scan(stlc); - stlc45xx_tx_setup(stlc); - stlc45xx_tx_edcf(stlc); - - ieee80211_wake_queues(stlc->hw); - break; - default: - break; - } -} - -static int stlc45xx_rx_txack(struct stlc45xx *stlc, struct sk_buff *skb) -{ - struct ieee80211_tx_info *info; - struct s_lm_control *control; - struct s_lmo_tx *tx; - struct txbuffer *entry; - int found = 0; - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - control = (struct s_lm_control *) skb->data; - tx = (struct s_lmo_tx *) (control + 1); - - if (list_empty(&stlc->tx_sent)) { - if (net_ratelimit()) - stlc45xx_warning("no frames waiting for " - "acknowledgement"); - return -1; - } - - list_for_each_entry(entry, &stlc->tx_sent, tx_list) { - if (control->handle == entry->handle) { - found = 1; - break; - } - } - - if (!found) { - if (net_ratelimit()) - stlc45xx_warning("couldn't find frame for tx ack 0x%x", - control->handle); - return -1; - } - - stlc45xx_debug(DEBUG_TX, "TX ACK 0x%x", entry->handle); - - if (entry->status_needed) { - info = IEEE80211_SKB_CB(entry->skb); - - if (!(tx->flags & LM_TX_FAILED)) { - /* frame was acked */ - info->flags |= IEEE80211_TX_STAT_ACK; - info->status.ack_signal = tx->rcpi / 2 - 110; - } - - skb_pull(entry->skb, entry->header_len); - - ieee80211_tx_status(stlc->hw, entry->skb); - } - - list_del(&entry->tx_list); - - stlc45xx_check_txsent(stlc); - if (list_empty(&stlc->tx_sent)) - /* there are no pending frames, we can stop the tx timeout - * timer */ - cancel_delayed_work(&stlc->work_tx_timeout); - - spin_lock_bh(&stlc->tx_lock); - - stlc45xx_txbuffer_free(stlc, entry); - - if (stlc->tx_queue_stopped && - stlc45xx_txbuffer_find(stlc, MAX_FRAME_LEN) != -1) { - stlc45xx_debug(DEBUG_QUEUE, "room in tx buffer, waking queues"); - ieee80211_wake_queues(stlc->hw); - stlc->tx_queue_stopped = 0; - } - - spin_unlock_bh(&stlc->tx_lock); - - return 0; -} - -static int stlc45xx_rx_control(struct stlc45xx *stlc, struct sk_buff *skb) -{ - struct s_lm_control *control; - int ret = 0; - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - control = (struct s_lm_control *) skb->data; - - switch (control->oid) { - case LM_OID_TX: - ret = stlc45xx_rx_txack(stlc, skb); - break; - case LM_OID_SETUP: - case LM_OID_SCAN: - case LM_OID_TRAP: - case LM_OID_EDCF: - case LM_OID_KEYCACHE: - case LM_OID_PSM: - case LM_OID_STATS: - case LM_OID_LED: - default: - stlc45xx_warning("unhandled rx control oid %d\n", - control->oid); - break; - } - - dev_kfree_skb(skb); - - return ret; -} - -/* copied from mac80211 */ -static void stlc45xx_parse_elems(u8 *start, size_t len, - struct stlc45xx_ie_tim **tim, - size_t *tim_len) -{ - size_t left = len; - u8 *pos = start; - - while (left >= 2) { - u8 id, elen; - - id = *pos++; - elen = *pos++; - left -= 2; - - if (elen > left) - return; - - switch (id) { - case WLAN_EID_TIM: - *tim = (struct stlc45xx_ie_tim *) pos; - *tim_len = elen; - break; - default: - break; - } - - left -= elen; - pos += elen; - } -} - -/* - * mac80211 doesn't have support for asking frames with PS-Poll, so let's - * implement in the driver for now. We have to add support to mac80211 - * later. - */ -static int stlc45xx_check_more_data(struct stlc45xx *stlc, struct sk_buff *skb) -{ - struct s_lm_data_in *data = (struct s_lm_data_in *) skb->data; - struct ieee80211_hdr *hdr; - size_t len; - u16 fc; - - hdr = (void *) skb->data + sizeof(*data); - len = skb->len - sizeof(*data); - - /* minimum frame length is the null frame length 24 bytes */ - if (len < 24) { - stlc45xx_warning("invalid frame length when checking for " - "more data"); - return -EINVAL; - } - - fc = le16_to_cpu(hdr->frame_control); - if (!(fc & IEEE80211_FCTL_FROMDS)) - /* this is not from DS */ - return 0; - - if (compare_ether_addr(hdr->addr1, stlc->mac_addr) != 0) - /* the frame was not for us */ - return 0; - - if (!(fc & IEEE80211_FCTL_MOREDATA)) { - /* AP has no more frames buffered for us */ - stlc45xx_debug(DEBUG_PSM, "all buffered frames retrieved"); - stlc->pspolling = false; - return 0; - } - - /* MOREDATA bit is set, let's ask for a new frame from the AP */ - stlc45xx_tx_pspoll(stlc, stlc->psm); - - return 0; -} - -/* - * mac80211 cannot read TIM from beacons, so let's add a hack to the - * driver. We have to add support to mac80211 later. - */ -static int stlc45xx_rx_data_beacon(struct stlc45xx *stlc, struct sk_buff *skb) -{ - struct s_lm_data_in *data = (struct s_lm_data_in *) skb->data; - size_t len = skb->len, tim_len = 0, baselen, pvbmap_len; - struct ieee80211_mgmt *mgmt; - struct stlc45xx_ie_tim *tim = NULL; - int bmap_offset, index, aid_bit; - - mgmt = (void *) skb->data + sizeof(*data); - - baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; - if (baselen > len) { - stlc45xx_warning("invalid baselen in beacon"); - return -EINVAL; - } - - stlc45xx_parse_elems(mgmt->u.beacon.variable, len - baselen, &tim, - &tim_len); - - if (!tim) { - stlc45xx_warning("didn't find tim from a beacon"); - return -EINVAL; - } - - bmap_offset = tim->bmap_control & 0xfe; - index = stlc->aid / 8 - bmap_offset; - - pvbmap_len = tim_len - 3; - if (index > pvbmap_len) - return -EINVAL; - - aid_bit = !!(tim->pvbmap[index] & (1 << stlc->aid % 8)); - - stlc45xx_debug(DEBUG_PSM, "fc 0x%x duration %d seq %d dtim %u " - "bmap_control 0x%x aid_bit %d", - mgmt->frame_control, mgmt->duration, mgmt->seq_ctrl >> 4, - tim->dtim_count, tim->bmap_control, aid_bit); - - if (!aid_bit) - return 0; - - stlc->pspolling = true; - stlc45xx_tx_pspoll(stlc, stlc->psm); - - return 0; -} - -static int stlc45xx_rx_data(struct stlc45xx *stlc, struct sk_buff *skb) -{ - struct ieee80211_rx_status status; - struct s_lm_data_in *data = (struct s_lm_data_in *) skb->data; - int align = 0; - u8 *p, align_len; - u16 len; - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - if (stlc->psm) { - if (data->flags & LM_IN_BEACON) - stlc45xx_rx_data_beacon(stlc, skb); - else if (stlc->pspolling && (data->flags & LM_IN_DATA)) - stlc45xx_check_more_data(stlc, skb); - } - - memset(&status, 0, sizeof(status)); - - status.freq = data->frequency; - status.signal = data->rcpi / 2 - 110; - - /* let's assume that maximum rcpi value is 140 (= 35 dBm) */ - status.qual = data->rcpi * 100 / 140; - - status.band = IEEE80211_BAND_2GHZ; - - /* - * FIXME: this gives warning from __ieee80211_rx() - * - * status.rate_idx = data->rate; - */ - - len = data->length; - - if (data->flags & LM_FLAG_ALIGN) - align = 1; - - skb_pull(skb, sizeof(*data)); - - if (align) { - p = skb->data; - align_len = *p; - skb_pull(skb, align_len); - } - - skb_trim(skb, len); - - stlc45xx_debug(DEBUG_RX, "rx data 0x%p %d B", skb->data, skb->len); - stlc45xx_dump(DEBUG_RX_CONTENT, skb->data, skb->len); - - memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); - ieee80211_rx(stlc->hw, skb); - - return 0; -} - - - -static int stlc45xx_rx(struct stlc45xx *stlc) -{ - struct s_lm_control *control; - struct sk_buff *skb; - int ret; - u16 len; - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - stlc45xx_wakeup(stlc); - - /* dummy read to flush SPI DMA controller bug */ - stlc45xx_read16(stlc, SPI_ADRS_GEN_PURP_1); - - len = stlc45xx_read16(stlc, SPI_ADRS_DMA_DATA); - - if (len == 0) { - stlc45xx_warning("rx request of zero bytes"); - return 0; - } - - skb = dev_alloc_skb(len); - if (!skb) { - stlc45xx_warning("could not alloc skb"); - return 0; - } - - stlc45xx_spi_read(stlc, SPI_ADRS_DMA_DATA, skb_put(skb, len), len); - - stlc45xx_sleep(stlc); - - stlc45xx_debug(DEBUG_RX, "rx frame 0x%p %d B", skb->data, skb->len); - stlc45xx_dump(DEBUG_RX_CONTENT, skb->data, skb->len); - - control = (struct s_lm_control *) skb->data; - - if (control->flags & LM_FLAG_CONTROL) - ret = stlc45xx_rx_control(stlc, skb); - else - ret = stlc45xx_rx_data(stlc, skb); - - return ret; -} - - -static irqreturn_t stlc45xx_interrupt(int irq, void *config) -{ - struct spi_device *spi = config; - struct stlc45xx *stlc = dev_get_drvdata(&spi->dev); - - stlc45xx_debug(DEBUG_IRQ, "IRQ"); - - queue_work(stlc->hw->workqueue, &stlc->work); - - return IRQ_HANDLED; -} - -static int stlc45xx_tx_frame(struct stlc45xx *stlc, u32 address, - void *buf, size_t len) -{ - struct s_dma_regs dma_regs; - unsigned long timeout; - int ret = 0; - u32 ints; - - stlc->tx_frames++; - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - stlc45xx_debug(DEBUG_TX, "tx frame 0x%p %zu B", buf, len); - stlc45xx_dump(DEBUG_TX_CONTENT, buf, len); - - stlc45xx_wakeup(stlc); - - dma_regs.cmd = SPI_DMA_WRITE_CTRL_ENABLE; - dma_regs.len = cpu_to_le16(len); - dma_regs.addr = cpu_to_le32(address); - - stlc45xx_spi_write(stlc, SPI_ADRS_DMA_WRITE_CTRL, &dma_regs, - sizeof(dma_regs)); - - stlc45xx_spi_write(stlc, SPI_ADRS_DMA_DATA, buf, len); - - timeout = jiffies + 2 * HZ; - ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS); - while (!(ints & SPI_HOST_INT_WR_READY)) { - if (time_after(jiffies, timeout)) { - stlc45xx_warning("WR_READY timeout"); - ret = -1; - goto out; - } - ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS); - } - - stlc45xx_int_ack(stlc, SPI_HOST_INT_WR_READY); - - stlc45xx_sleep(stlc); - -out: - return ret; -} - -static int stlc45xx_wq_tx(struct stlc45xx *stlc) -{ - struct txbuffer *entry; - int ret = 0; - - spin_lock_bh(&stlc->tx_lock); - - while (!list_empty(&stlc->tx_pending)) { - entry = list_entry(stlc->tx_pending.next, - struct txbuffer, tx_list); - - list_del_init(&entry->tx_list); - - spin_unlock_bh(&stlc->tx_lock); - - ret = stlc45xx_tx_frame(stlc, entry->frame_start, - entry->skb->data, entry->skb->len); - - spin_lock_bh(&stlc->tx_lock); - - if (ret < 0) { - /* frame transfer to firmware buffer failed */ - /* FIXME: report this to mac80211 */ - dev_kfree_skb(entry->skb); - stlc45xx_txbuffer_free(stlc, entry); - goto out; - } - - list_add(&entry->tx_list, &stlc->tx_sent); - queue_delayed_work(stlc->hw->workqueue, - &stlc->work_tx_timeout, - msecs_to_jiffies(TX_TIMEOUT)); - } - -out: - spin_unlock_bh(&stlc->tx_lock); - return ret; -} - -static void stlc45xx_work(struct work_struct *work) -{ - struct stlc45xx *stlc = container_of(work, struct stlc45xx, work); - u32 ints; - int ret; - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - mutex_lock(&stlc->mutex); - - if (stlc->fw_state == FW_STATE_OFF && - stlc->fw_state == FW_STATE_RESET) - goto out; - - ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS); - stlc45xx_debug(DEBUG_BH, "begin host_ints 0x%08x", ints); - - if (ints & SPI_HOST_INT_READY) { - stlc45xx_int_ready(stlc); - stlc45xx_int_ack(stlc, SPI_HOST_INT_READY); - } - - if (stlc->fw_state != FW_STATE_READY) - goto out; - - if (ints & SPI_HOST_INT_UPDATE) { - stlc45xx_int_ack(stlc, SPI_HOST_INT_UPDATE); - ret = stlc45xx_rx(stlc); - if (ret < 0) { - stlc45xx_reset(stlc); - goto out; - } - } - if (ints & SPI_HOST_INT_SW_UPDATE) { - stlc45xx_int_ack(stlc, SPI_HOST_INT_SW_UPDATE); - ret = stlc45xx_rx(stlc); - if (ret < 0) { - stlc45xx_reset(stlc); - goto out; - } - } - - ret = stlc45xx_wq_tx(stlc); - if (ret < 0) { - stlc45xx_reset(stlc); - goto out; - } - - ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS); - stlc45xx_debug(DEBUG_BH, "end host_ints 0x%08x", ints); - -out: - mutex_unlock(&stlc->mutex); -} - -static void stlc45xx_tx_edcf(struct stlc45xx *stlc) -{ - struct s_lm_control *control; - struct s_lmo_edcf *edcf; - size_t len, edcf_len; - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - edcf_len = sizeof(*edcf); - len = sizeof(*control) + edcf_len; - control = kzalloc(len, GFP_KERNEL); - edcf = (struct s_lmo_edcf *) (control + 1); - - control->flags = LM_FLAG_CONTROL | LM_CTRL_OPSET; - control->length = edcf_len; - control->oid = LM_OID_EDCF; - - edcf->slottime = 0x14; - edcf->sifs = 10; - edcf->eofpad = 6; - edcf->maxburst = 1500; - - edcf->queues[0].aifs = 2; - edcf->queues[0].pad0 = 1; - edcf->queues[0].cwmin = 3; - edcf->queues[0].cwmax = 7; - edcf->queues[0].txop = 47; - edcf->queues[1].aifs = 2; - edcf->queues[1].pad0 = 0; - edcf->queues[1].cwmin = 7; - edcf->queues[1].cwmax = 15; - edcf->queues[1].txop = 94; - edcf->queues[2].aifs = 3; - edcf->queues[2].pad0 = 0; - edcf->queues[2].cwmin = 15; - edcf->queues[2].cwmax = 1023; - edcf->queues[2].txop = 0; - edcf->queues[3].aifs = 7; - edcf->queues[3].pad0 = 0; - edcf->queues[3].cwmin = 15; - edcf->queues[3].cwmax = 1023; - edcf->queues[3].txop = 0; - edcf->queues[4].aifs = 13; - edcf->queues[4].pad0 = 99; - edcf->queues[4].cwmin = 3437; - edcf->queues[4].cwmax = 512; - edcf->queues[4].txop = 12; - edcf->queues[5].aifs = 142; - edcf->queues[5].pad0 = 109; - edcf->queues[5].cwmin = 8756; - edcf->queues[5].cwmax = 6; - edcf->queues[5].txop = 0; - edcf->queues[6].aifs = 4; - edcf->queues[6].pad0 = 0; - edcf->queues[6].cwmin = 0; - edcf->queues[6].cwmax = 58705; - edcf->queues[6].txop = 25716; - edcf->queues[7].aifs = 0; - edcf->queues[7].pad0 = 0; - edcf->queues[7].cwmin = 0; - edcf->queues[7].cwmax = 0; - edcf->queues[7].txop = 0; - - stlc45xx_tx_frame(stlc, FIRMWARE_CONFIG_START, control, len); - - kfree(control); -} - -static void stlc45xx_tx_setup(struct stlc45xx *stlc) -{ - struct s_lm_control *control; - struct s_lmo_setup *setup; - size_t len, setup_len; - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - setup_len = sizeof(*setup); - len = sizeof(*control) + setup_len; - control = kzalloc(len, GFP_KERNEL); - setup = (struct s_lmo_setup *) (control + 1); - - control->flags = LM_FLAG_CONTROL | LM_CTRL_OPSET; - control->length = setup_len; - control->oid = LM_OID_SETUP; - - setup->flags = LM_SETUP_INFRA; - setup->antenna = 2; - setup->rx_align = 0; - setup->rx_buffer = FIRMWARE_RXBUFFER_START; - setup->rx_mtu = FIRMWARE_MTU; - setup->frontend = 5; - setup->timeout = 0; - setup->truncate = 48896; - setup->bratemask = 0xffffffff; - setup->ref_clock = 644245094; - setup->lpf_bandwidth = 65535; - setup->osc_start_delay = 65535; - - memcpy(setup->macaddr, stlc->mac_addr, ETH_ALEN); - memcpy(setup->bssid, stlc->bssid, ETH_ALEN); - - stlc45xx_tx_frame(stlc, FIRMWARE_CONFIG_START, control, len); - - kfree(control); -} - -static void stlc45xx_tx_scan(struct stlc45xx *stlc) -{ - struct s_lm_control *control; - struct s_lmo_scan *scan; - size_t len, scan_len; - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - scan_len = sizeof(*scan); - len = sizeof(*control) + scan_len; - control = kzalloc(len, GFP_KERNEL); - scan = (struct s_lmo_scan *) (control + 1); - - control->flags = LM_FLAG_CONTROL | LM_CTRL_OPSET; - control->length = scan_len; - control->oid = LM_OID_SCAN; - - scan->flags = LM_SCAN_EXIT; - scan->bratemask = 0x15f; - scan->aloft[0] = 3; - scan->aloft[1] = 3; - scan->aloft[2] = 1; - scan->aloft[3] = 0; - scan->aloft[4] = 0; - scan->aloft[5] = 0; - scan->aloft[6] = 0; - scan->aloft[7] = 0; - - memcpy(&scan->rssical, &stlc->cal_rssi[(stlc->channel - 1) * - RSSI_CAL_LEN], - RSSI_CAL_LEN); - memcpy(&scan->channel, &stlc->cal_channels[(stlc->channel - 1) * - CHANNEL_CAL_LEN], - CHANNEL_CAL_LEN); - - stlc45xx_tx_frame(stlc, FIRMWARE_CONFIG_START, control, len); - - kfree(control); -} - -/* - * caller must hold mutex - */ -static int stlc45xx_tx_pspoll(struct stlc45xx *stlc, bool powersave) -{ - struct ieee80211_hdr *pspoll; - int payload_len, padding, i; - struct s_lm_data_out *data; - struct txbuffer *entry; - struct sk_buff *skb; - char *payload; - u16 fc; - - skb = dev_alloc_skb(stlc->hw->extra_tx_headroom + 16); - if (!skb) { - stlc45xx_warning("failed to allocate pspoll frame"); - return -ENOMEM; - } - skb_reserve(skb, stlc->hw->extra_tx_headroom); - - pspoll = (struct ieee80211_hdr *) skb_put(skb, 16); - memset(pspoll, 0, 16); - fc = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL; - if (powersave) - fc |= IEEE80211_FCTL_PM; - pspoll->frame_control = cpu_to_le16(fc); - pspoll->duration_id = cpu_to_le16(stlc->aid); - - /* aid in PS-Poll has its two MSBs each set to 1 */ - pspoll->duration_id |= cpu_to_le16(1 << 15) | cpu_to_le16(1 << 14); - - memcpy(pspoll->addr1, stlc->bssid, ETH_ALEN); - memcpy(pspoll->addr2, stlc->mac_addr, ETH_ALEN); - - stlc45xx_debug(DEBUG_PSM, "sending PS-Poll frame to %pM (powersave %d, " - "fc 0x%x, aid %d)", pspoll->addr1, - powersave, fc, stlc->aid); - - spin_lock_bh(&stlc->tx_lock); - - entry = stlc45xx_txbuffer_alloc(stlc, skb->len); - - spin_unlock_bh(&stlc->tx_lock); - - if (!entry) { - /* - * The queue should be stopped before the firmware buffer - * is full, so firmware buffer should always have enough - * space. - * - * But I'm too lazy and omit it for now. - */ - if (net_ratelimit()) - stlc45xx_warning("firmware tx buffer full is full " - "for null frame"); - return -ENOSPC; - } - - payload = skb->data; - payload_len = skb->len; - padding = (int) (skb->data - sizeof(*data)) & 3; - entry->header_len = sizeof(*data) + padding; - - entry->skb = skb; - entry->status_needed = false; - entry->handle = (u32) skb; - entry->lifetime = jiffies + msecs_to_jiffies(TX_FRAME_LIFETIME); - - stlc45xx_debug(DEBUG_TX, "tx data 0x%x (0x%p payload %d B " - "padding %d header_len %d)", - entry->handle, payload, payload_len, padding, - entry->header_len); - stlc45xx_dump(DEBUG_TX_CONTENT, payload, payload_len); - - data = (struct s_lm_data_out *) skb_push(skb, entry->header_len); - - memset(data, 0, entry->header_len); - - if (padding) - data->flags = LM_FLAG_ALIGN; - - data->flags = LM_OUT_BURST; - data->length = payload_len; - data->handle = entry->handle; - data->aid = 1; - data->rts_retries = 7; - data->retries = 7; - data->aloft_ctrl = 0; - data->crypt_offset = 58; - data->keytype = 0; - data->keylen = 0; - data->queue = LM_QUEUE_DATA3; - data->backlog = 32; - data->antenna = 2; - data->cts = 3; - data->power = 127; - - for (i = 0; i < 8; i++) - data->aloft[i] = 0; - - /* - * check if there's enough space in tx buffer - * - * FIXME: ignored for now - */ - - stlc45xx_tx_frame(stlc, entry->start, skb->data, skb->len); - - list_add(&entry->tx_list, &stlc->tx_sent); - - return 0; -} - -/* - * caller must hold mutex - * - * shamelessly stolen from mac80211/ieee80211_send_nullfunc - */ -static int stlc45xx_tx_nullfunc(struct stlc45xx *stlc, bool powersave) -{ - struct ieee80211_hdr *nullfunc; - int payload_len, padding, i; - struct s_lm_data_out *data; - struct txbuffer *entry; - struct sk_buff *skb; - char *payload; - u16 fc; - - skb = dev_alloc_skb(stlc->hw->extra_tx_headroom + 24); - if (!skb) { - stlc45xx_warning("failed to allocate buffer for null frame\n"); - return -ENOMEM; - } - skb_reserve(skb, stlc->hw->extra_tx_headroom); - - nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24); - memset(nullfunc, 0, 24); - fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | - IEEE80211_FCTL_TODS; - - if (powersave) - fc |= IEEE80211_FCTL_PM; - - nullfunc->frame_control = cpu_to_le16(fc); - memcpy(nullfunc->addr1, stlc->bssid, ETH_ALEN); - memcpy(nullfunc->addr2, stlc->mac_addr, ETH_ALEN); - memcpy(nullfunc->addr3, stlc->bssid, ETH_ALEN); - - stlc45xx_debug(DEBUG_PSM, "sending Null frame to %pM (powersave %d, " - "fc 0x%x)", nullfunc->addr1, powersave, fc); - - spin_lock_bh(&stlc->tx_lock); - - entry = stlc45xx_txbuffer_alloc(stlc, skb->len); - - spin_unlock_bh(&stlc->tx_lock); - - if (!entry) { - /* - * The queue should be stopped before the firmware buffer - * is full, so firmware buffer should always have enough - * space. - * - * But I'm too lazy and omit it for now. - */ - if (net_ratelimit()) - stlc45xx_warning("firmware tx buffer full is full " - "for null frame"); - return -ENOSPC; - } - - payload = skb->data; - payload_len = skb->len; - padding = (int) (skb->data - sizeof(*data)) & 3; - entry->header_len = sizeof(*data) + padding; - - entry->skb = skb; - entry->status_needed = false; - entry->handle = (u32) skb; - entry->lifetime = jiffies + msecs_to_jiffies(TX_FRAME_LIFETIME); - - stlc45xx_debug(DEBUG_TX, "tx data 0x%x (0x%p payload %d B " - "padding %d header_len %d)", - entry->handle, payload, payload_len, padding, - entry->header_len); - stlc45xx_dump(DEBUG_TX_CONTENT, payload, payload_len); - - data = (struct s_lm_data_out *) skb_push(skb, entry->header_len); - - memset(data, 0, entry->header_len); - - if (padding) - data->flags = LM_FLAG_ALIGN; - - data->flags = LM_OUT_BURST; - data->length = payload_len; - data->handle = entry->handle; - data->aid = 1; - data->rts_retries = 7; - data->retries = 7; - data->aloft_ctrl = 0; - data->crypt_offset = 58; - data->keytype = 0; - data->keylen = 0; - data->queue = LM_QUEUE_DATA3; - data->backlog = 32; - data->antenna = 2; - data->cts = 3; - data->power = 127; - - for (i = 0; i < 8; i++) - data->aloft[i] = 0; - - /* - * check if there's enough space in tx buffer - * - * FIXME: ignored for now - */ - - stlc45xx_tx_frame(stlc, entry->start, skb->data, skb->len); - - list_add(&entry->tx_list, &stlc->tx_sent); - - return 0; -} - -/* caller must hold mutex */ -static void stlc45xx_tx_psm(struct stlc45xx *stlc, bool enable) -{ - struct s_lm_control *control; - struct s_lmo_psm *psm; - size_t len, psm_len; - - WARN_ON(!stlc->associated); - WARN_ON(stlc->aid < 1); - WARN_ON(stlc->aid > 2007); - - psm_len = sizeof(*psm); - len = sizeof(*control) + psm_len; - control = kzalloc(len, GFP_KERNEL); - psm = (struct s_lmo_psm *) (control + 1); - - control->flags = LM_FLAG_CONTROL | LM_CTRL_OPSET; - control->length = psm_len; - control->oid = LM_OID_PSM; - - if (enable) - psm->flags |= LM_PSM; - - psm->aid = stlc->aid; - - psm->beacon_rcpi_skip_max = 60; - - psm->intervals[0].interval = 1; - psm->intervals[0].periods = 1; - psm->intervals[1].interval = 1; - psm->intervals[1].periods = 1; - psm->intervals[2].interval = 1; - psm->intervals[2].periods = 1; - psm->intervals[3].interval = 1; - psm->intervals[3].periods = 1; - - psm->nr = 0; - psm->exclude[0] = 0; - - stlc45xx_debug(DEBUG_PSM, "sending LM_OID_PSM (aid %d, interval %d)", - psm->aid, psm->intervals[0].interval); - - stlc45xx_tx_frame(stlc, FIRMWARE_CONFIG_START, control, len); - - kfree(control); -} - -static int stlc45xx_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct stlc45xx *stlc = hw->priv; - struct ieee80211_tx_info *info; - struct ieee80211_rate *rate; - int payload_len, padding, i; - struct s_lm_data_out *data; - struct txbuffer *entry; - char *payload; - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - spin_lock_bh(&stlc->tx_lock); - - entry = stlc45xx_txbuffer_alloc(stlc, skb->len); - if (!entry) { - /* the queue should be stopped before the firmware buffer - * is full, so firmware buffer should always have enough - * space */ - if (net_ratelimit()) - stlc45xx_warning("firmware buffer full"); - spin_unlock_bh(&stlc->tx_lock); - return NETDEV_TX_BUSY; - } - - info = IEEE80211_SKB_CB(skb); - - payload = skb->data; - payload_len = skb->len; - padding = (int) (skb->data - sizeof(*data)) & 3; - entry->header_len = sizeof(*data) + padding; - - entry->skb = skb; - entry->status_needed = true; - entry->handle = (u32) skb; - entry->lifetime = jiffies + msecs_to_jiffies(TX_FRAME_LIFETIME); - - stlc45xx_debug(DEBUG_TX, "tx data 0x%x (0x%p payload %d B " - "padding %d header_len %d)", - entry->handle, payload, payload_len, padding, - entry->header_len); - stlc45xx_dump(DEBUG_TX_CONTENT, payload, payload_len); - - data = (struct s_lm_data_out *) skb_push(skb, entry->header_len); - - memset(data, 0, entry->header_len); - - if (padding) - data->flags = LM_FLAG_ALIGN; - - data->flags = LM_OUT_BURST; - data->length = payload_len; - data->handle = entry->handle; - data->aid = 1; - data->rts_retries = 7; - data->retries = 7; - data->aloft_ctrl = 0; - data->crypt_offset = 58; - data->keytype = 0; - data->keylen = 0; - data->queue = 2; - data->backlog = 32; - data->antenna = 2; - data->cts = 3; - data->power = 127; - - for (i = 0; i < 8; i++) { - rate = ieee80211_get_tx_rate(stlc->hw, info); - data->aloft[i] = rate->hw_value; - } - - list_add_tail(&entry->tx_list, &stlc->tx_pending); - - /* check if there's enough space in tx buffer */ - if (stlc45xx_txbuffer_find(stlc, MAX_FRAME_LEN) == -1) { - stlc45xx_debug(DEBUG_QUEUE, "tx buffer full, stopping queues"); - stlc->tx_queue_stopped = 1; - ieee80211_stop_queues(stlc->hw); - } - - queue_work(stlc->hw->workqueue, &stlc->work); - - spin_unlock_bh(&stlc->tx_lock); - - return NETDEV_TX_OK; -} - -static int stlc45xx_op_start(struct ieee80211_hw *hw) -{ - struct stlc45xx *stlc = hw->priv; - unsigned long timeout; - int ret = 0; - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - mutex_lock(&stlc->mutex); - - stlc->fw_state = FW_STATE_BOOTING; - stlc->channel = 1; - - stlc45xx_power_on(stlc); - - ret = stlc45xx_upload_firmware(stlc); - if (ret < 0) { - stlc45xx_power_off(stlc); - goto out_unlock; - } - - stlc->tx_queue_stopped = 0; - - mutex_unlock(&stlc->mutex); - - timeout = msecs_to_jiffies(2000); - timeout = wait_for_completion_interruptible_timeout(&stlc->fw_comp, - timeout); - if (!timeout) { - stlc45xx_error("firmware boot failed"); - stlc45xx_power_off(stlc); - ret = -1; - goto out; - } - - stlc45xx_debug(DEBUG_BOOT, "firmware booted"); - - /* FIXME: should we take mutex just after wait_for_completion()? */ - mutex_lock(&stlc->mutex); - - WARN_ON(stlc->fw_state != FW_STATE_READY); - -out_unlock: - mutex_unlock(&stlc->mutex); - -out: - return ret; -} - -static void stlc45xx_op_stop(struct ieee80211_hw *hw) -{ - struct stlc45xx *stlc = hw->priv; - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - mutex_lock(&stlc->mutex); - - WARN_ON(stlc->fw_state != FW_STATE_READY); - - stlc45xx_power_off(stlc); - - /* FIXME: make sure that all work_structs have completed */ - - spin_lock_bh(&stlc->tx_lock); - stlc45xx_flush_queues(stlc); - spin_unlock_bh(&stlc->tx_lock); - - stlc->fw_state = FW_STATE_OFF; - - mutex_unlock(&stlc->mutex); -} - -static int stlc45xx_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct stlc45xx *stlc = hw->priv; - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - switch (conf->type) { - case NL80211_IFTYPE_STATION: - break; - default: - return -EOPNOTSUPP; - } - - memcpy(stlc->mac_addr, conf->mac_addr, ETH_ALEN); - - return 0; -} - -static void stlc45xx_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); -} - -static int stlc45xx_op_config(struct ieee80211_hw *hw, u32 changed) -{ - struct stlc45xx *stlc = hw->priv; - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - mutex_lock(&stlc->mutex); - - stlc->channel = hw->conf.channel->hw_value; - stlc45xx_tx_scan(stlc); - stlc45xx_tx_setup(stlc); - stlc45xx_tx_edcf(stlc); - - if ((hw->conf.flags & IEEE80211_CONF_PS) != stlc->psm) { - stlc->psm = hw->conf.flags & IEEE80211_CONF_PS; - if (stlc->associated) { - stlc45xx_tx_psm(stlc, stlc->psm); - stlc45xx_tx_nullfunc(stlc, stlc->psm); - } - } - - mutex_unlock(&stlc->mutex); - - return 0; -} - -static void stlc45xx_op_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - int mc_count, - struct dev_addr_list *mc_list) -{ - *total_flags = 0; -} - -static void stlc45xx_op_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u32 changed) -{ - struct stlc45xx *stlc = hw->priv; - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - mutex_lock(&stlc->mutex); - - memcpy(stlc->bssid, info->bssid, ETH_ALEN); - stlc45xx_tx_setup(stlc); - - mutex_unlock(&stlc->mutex); - - if (changed & BSS_CHANGED_ASSOC) { - stlc->associated = info->assoc; - if (info->assoc) - stlc->aid = info->aid; - else - stlc->aid = -1; - - if (stlc->psm) { - stlc45xx_tx_psm(stlc, stlc->psm); - stlc45xx_tx_nullfunc(stlc, stlc->psm); - } - } -} - - -/* can't be const, mac80211 writes to this */ -static struct ieee80211_rate stlc45xx_rates[] = { - { .bitrate = 10, .hw_value = 0, .hw_value_short = 0, }, - { .bitrate = 20, .hw_value = 1, .hw_value_short = 1, }, - { .bitrate = 55, .hw_value = 2, .hw_value_short = 2, }, - { .bitrate = 110, .hw_value = 3, .hw_value_short = 3, }, - { .bitrate = 60, .hw_value = 4, .hw_value_short = 4, }, - { .bitrate = 90, .hw_value = 5, .hw_value_short = 5, }, - { .bitrate = 120, .hw_value = 6, .hw_value_short = 6, }, - { .bitrate = 180, .hw_value = 7, .hw_value_short = 7, }, - { .bitrate = 240, .hw_value = 8, .hw_value_short = 8, }, - { .bitrate = 360, .hw_value = 9, .hw_value_short = 9, }, - { .bitrate = 480, .hw_value = 10, .hw_value_short = 10, }, - { .bitrate = 540, .hw_value = 11, .hw_value_short = 11, }, -}; - -/* can't be const, mac80211 writes to this */ -static struct ieee80211_channel stlc45xx_channels[] = { - { .hw_value = 1, .center_freq = 2412}, - { .hw_value = 2, .center_freq = 2417}, - { .hw_value = 3, .center_freq = 2422}, - { .hw_value = 4, .center_freq = 2427}, - { .hw_value = 5, .center_freq = 2432}, - { .hw_value = 6, .center_freq = 2437}, - { .hw_value = 7, .center_freq = 2442}, - { .hw_value = 8, .center_freq = 2447}, - { .hw_value = 9, .center_freq = 2452}, - { .hw_value = 10, .center_freq = 2457}, - { .hw_value = 11, .center_freq = 2462}, - { .hw_value = 12, .center_freq = 2467}, - { .hw_value = 13, .center_freq = 2472}, -}; - -/* can't be const, mac80211 writes to this */ -static struct ieee80211_supported_band stlc45xx_band_2ghz = { - .channels = stlc45xx_channels, - .n_channels = ARRAY_SIZE(stlc45xx_channels), - .bitrates = stlc45xx_rates, - .n_bitrates = ARRAY_SIZE(stlc45xx_rates), -}; - -static const struct ieee80211_ops stlc45xx_ops = { - .start = stlc45xx_op_start, - .stop = stlc45xx_op_stop, - .add_interface = stlc45xx_op_add_interface, - .remove_interface = stlc45xx_op_remove_interface, - .config = stlc45xx_op_config, - .configure_filter = stlc45xx_op_configure_filter, - .tx = stlc45xx_op_tx, - .bss_info_changed = stlc45xx_op_bss_info_changed, -}; - -static int stlc45xx_register_mac80211(struct stlc45xx *stlc) -{ - /* FIXME: SET_IEEE80211_PERM_ADDR() requires default_mac_addr - to be non-const for some strange reason */ - static u8 default_mac_addr[ETH_ALEN] = { - 0x00, 0x02, 0xee, 0xc0, 0xff, 0xee - }; - int ret; - - SET_IEEE80211_PERM_ADDR(stlc->hw, default_mac_addr); - - ret = ieee80211_register_hw(stlc->hw); - if (ret) { - stlc45xx_error("unable to register mac80211 hw: %d", ret); - return ret; - } - - return 0; -} - -static void stlc45xx_device_release(struct device *dev) -{ - -} - -static struct platform_device stlc45xx_device = { - .name = "stlc45xx", - .id = -1, - - /* device model insists to have a release function */ - .dev = { - .release = stlc45xx_device_release, - }, -}; - -static int __devinit stlc45xx_probe(struct spi_device *spi) -{ - struct stlc45xx *stlc; - struct ieee80211_hw *hw; - int ret; - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - /* mac80211 alloc */ - hw = ieee80211_alloc_hw(sizeof(*stlc), &stlc45xx_ops); - if (!hw) { - stlc45xx_error("could not alloc ieee80211_hw"); - ret = -ENOMEM; - goto out; - } - - /* mac80211 clears hw->priv */ - stlc = hw->priv; - - stlc->hw = hw; - dev_set_drvdata(&spi->dev, stlc); - stlc->spi = spi; - - spi->bits_per_word = 16; - spi->max_speed_hz = 24000000; - - ret = spi_setup(spi); - if (ret < 0) - stlc45xx_error("spi_setup failed"); - - ret = gpio_request(stlc45xx_gpio_power, "stlc45xx power"); - if (ret < 0) { - stlc45xx_error("power GPIO request failed: %d", ret); - return ret; - } - - ret = gpio_request(stlc45xx_gpio_irq, "stlc45xx irq"); - if (ret < 0) { - stlc45xx_error("irq GPIO request failed: %d", ret); - goto out; - } - - gpio_direction_output(stlc45xx_gpio_power, 0); - gpio_direction_input(stlc45xx_gpio_irq); - - ret = request_irq(gpio_to_irq(stlc45xx_gpio_irq), - stlc45xx_interrupt, IRQF_DISABLED, "stlc45xx", - stlc->spi); - if (ret < 0) - /* FIXME: handle the error */ - stlc45xx_error("request_irq() failed"); - - set_irq_type(gpio_to_irq(stlc45xx_gpio_irq), - IRQ_TYPE_EDGE_RISING); - - disable_irq(gpio_to_irq(stlc45xx_gpio_irq)); - - ret = platform_device_register(&stlc45xx_device); - if (ret) { - stlc45xx_error("Couldn't register wlan_omap device."); - return ret; - } - dev_set_drvdata(&stlc45xx_device.dev, stlc); - - INIT_WORK(&stlc->work, stlc45xx_work); - INIT_WORK(&stlc->work_reset, stlc45xx_work_reset); - INIT_DELAYED_WORK(&stlc->work_tx_timeout, stlc45xx_work_tx_timeout); - mutex_init(&stlc->mutex); - init_completion(&stlc->fw_comp); - spin_lock_init(&stlc->tx_lock); - INIT_LIST_HEAD(&stlc->txbuffer); - INIT_LIST_HEAD(&stlc->tx_pending); - INIT_LIST_HEAD(&stlc->tx_sent); - - hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; - /* four bytes for padding */ - hw->extra_tx_headroom = sizeof(struct s_lm_data_out) + 4; - - /* unit us */ - hw->channel_change_time = 1000; - - hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &stlc45xx_band_2ghz; - - SET_IEEE80211_DEV(hw, &spi->dev); - - BUILD_BUG_ON(sizeof(default_cal_rssi) != RSSI_CAL_ARRAY_LEN); - BUILD_BUG_ON(sizeof(default_cal_channels) != CHANNEL_CAL_ARRAY_LEN); - - stlc->cal_rssi = kmemdup(default_cal_rssi, RSSI_CAL_ARRAY_LEN, - GFP_KERNEL); - stlc->cal_channels = kmemdup(default_cal_channels, - CHANNEL_CAL_ARRAY_LEN, - GFP_KERNEL); - - ret = device_create_file(&stlc45xx_device.dev, &dev_attr_cal_rssi); - if (ret < 0) { - stlc45xx_error("failed to create sysfs file cal_rssi"); - goto out; - } - - ret = device_create_file(&stlc45xx_device.dev, &dev_attr_cal_channels); - if (ret < 0) { - stlc45xx_error("failed to create sysfs file cal_channels"); - goto out; - } - - ret = device_create_file(&stlc45xx_device.dev, &dev_attr_tx_buf); - if (ret < 0) { - stlc45xx_error("failed to create sysfs file tx_buf"); - goto out; - } - - ret = stlc45xx_register_mac80211(stlc); - if (ret < 0) - goto out; - - stlc45xx_info("v" DRIVER_VERSION " loaded"); - - stlc45xx_info("config buffer 0x%x-0x%x", - FIRMWARE_CONFIG_START, FIRMWARE_CONFIG_END); - stlc45xx_info("tx 0x%x-0x%x, rx 0x%x-0x%x", - FIRMWARE_TXBUFFER_START, FIRMWARE_TXBUFFER_END, - FIRMWARE_RXBUFFER_START, FIRMWARE_RXBUFFER_END); - -out: - return ret; -} - -static int __devexit stlc45xx_remove(struct spi_device *spi) -{ - struct stlc45xx *stlc = dev_get_drvdata(&spi->dev); - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - platform_device_unregister(&stlc45xx_device); - - ieee80211_unregister_hw(stlc->hw); - - free_irq(gpio_to_irq(stlc45xx_gpio_irq), spi); - - gpio_free(stlc45xx_gpio_power); - gpio_free(stlc45xx_gpio_irq); - - /* FIXME: free cal_channels and cal_rssi? */ - - kfree(stlc->fw); - - mutex_destroy(&stlc->mutex); - - /* frees also stlc */ - ieee80211_free_hw(stlc->hw); - stlc = NULL; - - return 0; -} - - -static struct spi_driver stlc45xx_spi_driver = { - .driver = { - /* use cx3110x name because board-n800.c uses that for the - * SPI port */ - .name = "cx3110x", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - - .probe = stlc45xx_probe, - .remove = __devexit_p(stlc45xx_remove), -}; - -static int __init stlc45xx_init(void) -{ - int ret; - - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - ret = spi_register_driver(&stlc45xx_spi_driver); - if (ret < 0) { - stlc45xx_error("failed to register SPI driver: %d", ret); - goto out; - } - -out: - return ret; -} - -static void __exit stlc45xx_exit(void) -{ - stlc45xx_debug(DEBUG_FUNC, "%s", __func__); - - spi_unregister_driver(&stlc45xx_spi_driver); - - stlc45xx_info("unloaded"); -} - -module_init(stlc45xx_init); -module_exit(stlc45xx_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>"); -MODULE_ALIAS("spi:cx3110x"); diff --git a/drivers/staging/stlc45xx/stlc45xx.h b/drivers/staging/stlc45xx/stlc45xx.h deleted file mode 100644 index ac96bbbde79f..000000000000 --- a/drivers/staging/stlc45xx/stlc45xx.h +++ /dev/null @@ -1,283 +0,0 @@ -/* - * This file is part of stlc45xx - * - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). - * - * Contact: Kalle Valo <kalle.valo@nokia.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include <linux/mutex.h> -#include <linux/list.h> -#include <net/mac80211.h> - -#include "stlc45xx_lmac.h" - -#define DRIVER_NAME "stlc45xx" -#define DRIVER_VERSION "0.1.3" - -#define DRIVER_PREFIX DRIVER_NAME ": " - -enum { - DEBUG_NONE = 0, - DEBUG_FUNC = 1 << 0, - DEBUG_IRQ = 1 << 1, - DEBUG_BH = 1 << 2, - DEBUG_RX = 1 << 3, - DEBUG_RX_CONTENT = 1 << 5, - DEBUG_TX = 1 << 6, - DEBUG_TX_CONTENT = 1 << 8, - DEBUG_TXBUFFER = 1 << 9, - DEBUG_QUEUE = 1 << 10, - DEBUG_BOOT = 1 << 11, - DEBUG_PSM = 1 << 12, - DEBUG_ALL = ~0, -}; - -#define DEBUG_LEVEL DEBUG_NONE -/* #define DEBUG_LEVEL DEBUG_ALL */ -/* #define DEBUG_LEVEL (DEBUG_TX | DEBUG_RX | DEBUG_IRQ) */ -/* #define DEBUG_LEVEL (DEBUG_TX | DEBUG_MEMREGION | DEBUG_QUEUE) */ -/* #define DEBUG_LEVEL (DEBUG_MEMREGION | DEBUG_QUEUE) */ - -#define stlc45xx_error(fmt, arg...) \ - printk(KERN_ERR DRIVER_PREFIX "ERROR " fmt "\n", ##arg) - -#define stlc45xx_warning(fmt, arg...) \ - printk(KERN_WARNING DRIVER_PREFIX "WARNING " fmt "\n", ##arg) - -#define stlc45xx_info(fmt, arg...) \ - printk(KERN_INFO DRIVER_PREFIX fmt "\n", ##arg) - -#define stlc45xx_debug(level, fmt, arg...) \ - do { \ - if (level & DEBUG_LEVEL) \ - printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg); \ - } while (0) - -#define stlc45xx_dump(level, buf, len) \ - do { \ - if (level & DEBUG_LEVEL) \ - print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, \ - 16, 1, buf, len, 1); \ - } while (0) - -#define MAC2STR(a) ((a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]) -#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" - -/* Bit 15 is read/write bit; ON = READ, OFF = WRITE */ -#define ADDR_READ_BIT_15 0x8000 - -#define SPI_ADRS_ARM_INTERRUPTS 0x00 -#define SPI_ADRS_ARM_INT_EN 0x04 - -#define SPI_ADRS_HOST_INTERRUPTS 0x08 -#define SPI_ADRS_HOST_INT_EN 0x0c -#define SPI_ADRS_HOST_INT_ACK 0x10 - -#define SPI_ADRS_GEN_PURP_1 0x14 -#define SPI_ADRS_GEN_PURP_2 0x18 - -/* high word */ -#define SPI_ADRS_DEV_CTRL_STAT 0x26 - -#define SPI_ADRS_DMA_DATA 0x28 - -#define SPI_ADRS_DMA_WRITE_CTRL 0x2c -#define SPI_ADRS_DMA_WRITE_LEN 0x2e -#define SPI_ADRS_DMA_WRITE_BASE 0x30 - -#define SPI_ADRS_DMA_READ_CTRL 0x34 -#define SPI_ADRS_DMA_READ_LEN 0x36 -#define SPI_ADRS_DMA_READ_BASE 0x38 - -#define SPI_CTRL_STAT_HOST_OVERRIDE 0x8000 -#define SPI_CTRL_STAT_START_HALTED 0x4000 -#define SPI_CTRL_STAT_RAM_BOOT 0x2000 -#define SPI_CTRL_STAT_HOST_RESET 0x1000 -#define SPI_CTRL_STAT_HOST_CPU_EN 0x0800 - -#define SPI_DMA_WRITE_CTRL_ENABLE 0x0001 -#define SPI_DMA_READ_CTRL_ENABLE 0x0001 -#define HOST_ALLOWED (1 << 7) - -#define FIRMWARE_ADDRESS 0x20000 - -#define SPI_TIMEOUT 100 /* msec */ - -#define SPI_MAX_TX_PACKETS 32 - -#define SPI_MAX_PACKET_SIZE 32767 - -#define SPI_TARGET_INT_WAKEUP 0x00000001 -#define SPI_TARGET_INT_SLEEP 0x00000002 -#define SPI_TARGET_INT_RDDONE 0x00000004 - -#define SPI_TARGET_INT_CTS 0x00004000 -#define SPI_TARGET_INT_DR 0x00008000 - -#define SPI_HOST_INT_READY 0x00000001 -#define SPI_HOST_INT_WR_READY 0x00000002 -#define SPI_HOST_INT_SW_UPDATE 0x00000004 -#define SPI_HOST_INT_UPDATE 0x10000000 - -/* clear to send */ -#define SPI_HOST_INT_CTS 0x00004000 - -/* data ready */ -#define SPI_HOST_INT_DR 0x00008000 - -#define SPI_HOST_INTS_DEFAULT \ - (SPI_HOST_INT_READY | SPI_HOST_INT_UPDATE | SPI_HOST_INT_SW_UPDATE) - -#define TARGET_BOOT_SLEEP 50 - -/* The firmware buffer is divided into three areas: - * - * o config area (for control commands) - * o tx buffer - * o rx buffer - */ -#define FIRMWARE_BUFFER_START 0x20200 -#define FIRMWARE_BUFFER_END 0x27c60 -#define FIRMWARE_BUFFER_LEN (FIRMWARE_BUFFER_END - FIRMWARE_BUFFER_START) -#define FIRMWARE_MTU 3240 -#define FIRMWARE_CONFIG_PAYLOAD_LEN 1024 -#define FIRMWARE_CONFIG_START FIRMWARE_BUFFER_START -#define FIRMWARE_CONFIG_LEN (sizeof(struct s_lm_control) + \ - FIRMWARE_CONFIG_PAYLOAD_LEN) -#define FIRMWARE_CONFIG_END (FIRMWARE_CONFIG_START + FIRMWARE_CONFIG_LEN - 1) -#define FIRMWARE_RXBUFFER_LEN (5 * FIRMWARE_MTU + 1024) -#define FIRMWARE_RXBUFFER_START (FIRMWARE_BUFFER_END - FIRMWARE_RXBUFFER_LEN) -#define FIRMWARE_RXBUFFER_END (FIRMWARE_RXBUFFER_START + \ - FIRMWARE_RXBUFFER_LEN - 1) -#define FIRMWARE_TXBUFFER_START (FIRMWARE_BUFFER_START + FIRMWARE_CONFIG_LEN) -#define FIRMWARE_TXBUFFER_LEN (FIRMWARE_BUFFER_LEN - FIRMWARE_CONFIG_LEN - \ - FIRMWARE_RXBUFFER_LEN) -#define FIRMWARE_TXBUFFER_END (FIRMWARE_TXBUFFER_START + \ - FIRMWARE_TXBUFFER_LEN - 1) - -#define FIRMWARE_TXBUFFER_HEADER 100 -#define FIRMWARE_TXBUFFER_TRAILER 4 - -/* FIXME: come up with a proper value */ -#define MAX_FRAME_LEN 2500 - -/* unit is ms */ -#define TX_FRAME_LIFETIME 2000 -#define TX_TIMEOUT 4000 - -#define SUPPORTED_CHANNELS 13 - -/* FIXME */ -/* #define CHANNEL_CAL_LEN offsetof(struct s_lmo_scan, bratemask) - \ */ -/* offsetof(struct s_lmo_scan, channel) */ -#define CHANNEL_CAL_LEN 292 -#define CHANNEL_CAL_ARRAY_LEN (SUPPORTED_CHANNELS * CHANNEL_CAL_LEN) -/* FIXME */ -/* #define RSSI_CAL_LEN sizeof(struct s_lmo_scan) - \ */ -/* offsetof(struct s_lmo_scan, rssical) */ -#define RSSI_CAL_LEN 8 -#define RSSI_CAL_ARRAY_LEN (SUPPORTED_CHANNELS * RSSI_CAL_LEN) - -struct s_dma_regs { - unsigned short cmd; - unsigned short len; - unsigned long addr; -}; - -struct stlc45xx_ie_tim { - u8 dtim_count; - u8 dtim_period; - u8 bmap_control; - u8 pvbmap[251]; -}; - -struct txbuffer { - /* can be removed when switched to skb queue */ - struct list_head tx_list; - - struct list_head buffer_list; - - int start; - int frame_start; - int end; - - struct sk_buff *skb; - u32 handle; - - bool status_needed; - - int header_len; - - /* unit jiffies */ - unsigned long lifetime; -}; - -enum fw_state { - FW_STATE_OFF, - FW_STATE_BOOTING, - FW_STATE_READY, - FW_STATE_RESET, - FW_STATE_RESETTING, -}; - -struct stlc45xx { - struct ieee80211_hw *hw; - struct spi_device *spi; - struct work_struct work; - struct work_struct work_reset; - struct delayed_work work_tx_timeout; - struct mutex mutex; - struct completion fw_comp; - - - u8 bssid[ETH_ALEN]; - u8 mac_addr[ETH_ALEN]; - int channel; - - u8 *cal_rssi; - u8 *cal_channels; - - enum fw_state fw_state; - - spinlock_t tx_lock; - - /* protected by tx_lock */ - struct list_head txbuffer; - - /* protected by tx_lock */ - struct list_head tx_pending; - - /* protected by tx_lock */ - int tx_queue_stopped; - - /* protected by mutex */ - struct list_head tx_sent; - - int tx_frames; - - u8 *fw; - int fw_len; - - bool psm; - bool associated; - int aid; - bool pspolling; -}; - - diff --git a/drivers/staging/stlc45xx/stlc45xx_lmac.h b/drivers/staging/stlc45xx/stlc45xx_lmac.h deleted file mode 100644 index af5db801347f..000000000000 --- a/drivers/staging/stlc45xx/stlc45xx_lmac.h +++ /dev/null @@ -1,434 +0,0 @@ -/************************************************************************ -* This is the LMAC API interface header file for STLC4560. * -* Copyright (C) 2007 Conexant Systems, Inc. * -* 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. * -* * -* You should have received a copy of the GNU General Public License * -* along with this program. If not, see <http://www.gnu.org/licenses/>.* -*************************************************************************/ - -#ifndef __lmac_h__ -#define __lmac_h__ - -#define LM_TOP_VARIANT 0x0506 -#define LM_BOTTOM_VARIANT 0x0506 - -/* - * LMAC - UMAC interface definition: - */ - -#define LM_FLAG_CONTROL 0x8000 -#define LM_FLAG_ALIGN 0x4000 - -#define LM_CTRL_OPSET 0x0001 - -#define LM_OUT_PROMISC 0x0001 -#define LM_OUT_TIMESTAMP 0x0002 -#define LM_OUT_SEQNR 0x0004 -#define LM_OUT_BURST 0x0010 -#define LM_OUT_NOCANCEL 0x0020 -#define LM_OUT_CLEARTIM 0x0040 -#define LM_OUT_HITCHHIKE 0x0080 -#define LM_OUT_COMPRESS 0x0100 -#define LM_OUT_CONCAT 0x0200 -#define LM_OUT_PCS_ACCEPT 0x0400 -#define LM_OUT_WAITEOSP 0x0800 - - -#define LM_ALOFT_SP 0x10 -#define LM_ALOFT_CTS 0x20 -#define LM_ALOFT_RTS 0x40 -#define LM_ALOFT_MASK 0x1f -#define LM_ALOFT_RATE 0x0f - -#define LM_IN_FCS_GOOD 0x0001 -#define LM_IN_MATCH_MAC 0x0002 -#define LM_IN_MCBC 0x0004 -#define LM_IN_BEACON 0x0008 -#define LM_IN_MATCH_BSS 0x0010 -#define LM_IN_BCAST_BSS 0x0020 -#define LM_IN_DATA 0x0040 -#define LM_IN_TRUNCATED 0x0080 - -#define LM_IN_TRANSPARENT 0x0200 - -#define LM_QUEUE_BEACON 0 -#define LM_QUEUE_SCAN 1 -#define LM_QUEUE_MGT 2 -#define LM_QUEUE_MCBC 3 -#define LM_QUEUE_DATA 4 -#define LM_QUEUE_DATA0 4 -#define LM_QUEUE_DATA1 5 -#define LM_QUEUE_DATA2 6 -#define LM_QUEUE_DATA3 7 - -#define LM_SETUP_INFRA 0x0001 -#define LM_SETUP_IBSS 0x0002 -#define LM_SETUP_TRANSPARENT 0x0008 -#define LM_SETUP_PROMISCUOUS 0x0010 -#define LM_SETUP_HIBERNATE 0x0020 -#define LM_SETUP_NOACK 0x0040 -#define LM_SETUP_RX_DISABLED 0x0080 - -#define LM_ANTENNA_0 0 -#define LM_ANTENNA_1 1 -#define LM_ANTENNA_DIVERSITY 2 - -#define LM_TX_FAILED 0x0001 -#define LM_TX_PSM 0x0002 -#define LM_TX_PSM_CANCELLED 0x0004 - -#define LM_SCAN_EXIT 0x0001 -#define LM_SCAN_TRAP 0x0002 -#define LM_SCAN_ACTIVE 0x0004 -#define LM_SCAN_FILTER 0x0008 - -#define LM_PSM 0x0001 -#define LM_PSM_DTIM 0x0002 -#define LM_PSM_MCBC 0x0004 -#define LM_PSM_CHECKSUM 0x0008 -#define LM_PSM_SKIP_MORE_DATA 0x0010 -#define LM_PSM_BEACON_TIMEOUT 0x0020 -#define LM_PSM_HFOSLEEP 0x0040 -#define LM_PSM_AUTOSWITCH_SLEEP 0x0080 -#define LM_PSM_LPIT 0x0100 -#define LM_PSM_BF_UCAST_SKIP 0x0200 -#define LM_PSM_BF_MCAST_SKIP 0x0400 - -/* hfosleep */ -#define LM_PSM_SLEEP_OPTION_MASK (LM_PSM_AUTOSWITCH_SLEEP | LM_PSM_HFOSLEEP) -#define LM_PSM_SLEEP_OPTION_SHIFT 6 -/* hfosleepend */ -#define LM_PSM_BF_OPTION_MASK (LM_PSM_BF_MCAST_SKIP | LM_PSM_BF_UCAST_SKIP) -#define LM_PSM_BF_OPTION_SHIFT 9 - - -#define LM_PRIVACC_WEP 0x01 -#define LM_PRIVACC_TKIP 0x02 -#define LM_PRIVACC_MICHAEL 0x04 -#define LM_PRIVACC_CCX_KP 0x08 -#define LM_PRIVACC_CCX_MIC 0x10 -#define LM_PRIVACC_AES_CCMP 0x20 - -/* size of s_lm_descr in words */ -#define LM_DESCR_SIZE_WORDS 11 - -#ifndef __ASSEMBLER__ - -enum { - LM_MODE_CLIENT = 0, - LM_MODE_AP -}; - -struct s_lm_descr { - uint16_t modes; - uint16_t flags; - uint32_t buffer_start; - uint32_t buffer_end; - uint8_t header; - uint8_t trailer; - uint8_t tx_queues; - uint8_t tx_depth; - uint8_t privacy; - uint8_t rx_keycache; - uint8_t tim_size; - uint8_t pad1; - uint8_t rates[16]; - uint32_t link; - uint16_t mtu; -}; - - -struct s_lm_control { - uint16_t flags; - uint16_t length; - uint32_t handle; - uint16_t oid; - uint16_t pad; - /* uint8_t data[]; */ -}; - -enum { - LM_PRIV_NONE = 0, - LM_PRIV_WEP, - LM_PRIV_TKIP, - LM_PRIV_TKIPMICHAEL, - LM_PRIV_CCX_WEPMIC, - LM_PRIV_CCX_KPMIC, - LM_PRIV_CCX_KP, - LM_PRIV_AES_CCMP -}; - -enum { - LM_DECRYPT_NONE, - LM_DECRYPT_OK, - LM_DECRYPT_NOKEY, - LM_DECRYPT_NOMICHAEL, - LM_DECRYPT_NOCKIPMIC, - LM_DECRYPT_FAIL_WEP, - LM_DECRYPT_FAIL_TKIP, - LM_DECRYPT_FAIL_MICHAEL, - LM_DECRYPT_FAIL_CKIPKP, - LM_DECRYPT_FAIL_CKIPMIC, - LM_DECRYPT_FAIL_AESCCMP -}; - -struct s_lm_data_out { - uint16_t flags; - uint16_t length; - uint32_t handle; - uint16_t aid; - uint8_t rts_retries; - uint8_t retries; - uint8_t aloft[8]; - uint8_t aloft_ctrl; - uint8_t crypt_offset; - uint8_t keytype; - uint8_t keylen; - uint8_t key[16]; - uint8_t queue; - uint8_t backlog; - uint16_t durations[4]; - uint8_t antenna; - uint8_t cts; - int16_t power; - uint8_t pad[2]; - /*uint8_t data[];*/ -}; - -#define LM_RCPI_INVALID (0xff) - -struct s_lm_data_in { - uint16_t flags; - uint16_t length; - uint16_t frequency; - uint8_t antenna; - uint8_t rate; - uint8_t rcpi; - uint8_t sq; - uint8_t decrypt; - uint8_t rssi_raw; - uint32_t clock[2]; - /*uint8_t data[];*/ -}; - -union u_lm_data { - struct s_lm_data_out out; - struct s_lm_data_in in; -}; - -enum { - LM_OID_SETUP = 0, - LM_OID_SCAN = 1, - LM_OID_TRAP = 2, - LM_OID_EDCF = 3, - LM_OID_KEYCACHE = 4, - LM_OID_PSM = 6, - LM_OID_TXCANCEL = 7, - LM_OID_TX = 8, - LM_OID_BURST = 9, - LM_OID_STATS = 10, - LM_OID_LED = 13, - LM_OID_TIMER = 15, - LM_OID_NAV = 20, - LM_OID_PCS = 22, - LM_OID_BT_BALANCER = 28, - LM_OID_GROUP_ADDRESS_TABLE = 30, - LM_OID_ARPTABLE = 31, - LM_OID_BT_OPTIONS = 35 -}; - -enum { - LM_FRONTEND_UNKNOWN = 0, - LM_FRONTEND_DUETTE3, - LM_FRONTEND_DUETTE2, - LM_FRONTEND_FRISBEE, - LM_FRONTEND_CROSSBOW, - LM_FRONTEND_LONGBOW -}; - - -#define INVALID_LPF_BANDWIDTH 0xffff -#define INVALID_OSC_START_DELAY 0xffff - -struct s_lmo_setup { - uint16_t flags; - uint8_t macaddr[6]; - uint8_t bssid[6]; - uint8_t antenna; - uint8_t rx_align; - uint32_t rx_buffer; - uint16_t rx_mtu; - uint16_t frontend; - uint16_t timeout; - uint16_t truncate; - uint32_t bratemask; - uint8_t sbss_offset; - uint8_t mcast_window; - uint8_t rx_rssi_threshold; - uint8_t rx_ed_threshold; - uint32_t ref_clock; - uint16_t lpf_bandwidth; - uint16_t osc_start_delay; -}; - - -struct s_lmo_scan { - uint16_t flags; - uint16_t dwell; - uint8_t channel[292]; - uint32_t bratemask; - uint8_t aloft[8]; - uint8_t rssical[8]; -}; - - -enum { - LM_TRAP_SCAN = 0, - LM_TRAP_TIMER, - LM_TRAP_BEACON_TX, - LM_TRAP_FAA_RADIO_ON, - LM_TRAP_FAA_RADIO_OFF, - LM_TRAP_RADAR, - LM_TRAP_NO_BEACON, - LM_TRAP_TBTT, - LM_TRAP_SCO_ENTER, - LM_TRAP_SCO_EXIT -}; - -struct s_lmo_trap { - uint16_t event; - uint16_t frequency; -}; - -struct s_lmo_timer { - uint32_t interval; -}; - -struct s_lmo_nav { - uint32_t period; -}; - - -struct s_lmo_edcf_queue; - -struct s_lmo_edcf { - uint8_t flags; - uint8_t slottime; - uint8_t sifs; - uint8_t eofpad; - struct s_lmo_edcf_queue { - uint8_t aifs; - uint8_t pad0; - uint16_t cwmin; - uint16_t cwmax; - uint16_t txop; - } queues[8]; - uint8_t mapping[4]; - uint16_t maxburst; - uint16_t round_trip_delay; -}; - -struct s_lmo_keycache { - uint8_t entry; - uint8_t keyid; - uint8_t address[6]; - uint8_t pad[2]; - uint8_t keytype; - uint8_t keylen; - uint8_t key[24]; -}; - - -struct s_lm_interval; - -struct s_lmo_psm { - uint16_t flags; - uint16_t aid; - struct s_lm_interval { - uint16_t interval; - uint16_t periods; - } intervals[4]; - /* uint16_t pad; */ - uint8_t beacon_rcpi_skip_max; - uint8_t rcpi_delta_threshold; - uint8_t nr; - uint8_t exclude[1]; -}; - -#define MC_FILTER_ADDRESS_NUM 4 - -struct s_lmo_group_address_table { - uint16_t filter_enable; - uint16_t num_address; - uint8_t macaddr_list[MC_FILTER_ADDRESS_NUM][6]; -}; - -struct s_lmo_txcancel { - uint32_t address[1]; -}; - - -struct s_lmo_tx { - uint8_t flags; - uint8_t retries; - uint8_t rcpi; - uint8_t sq; - uint16_t seqctrl; - uint8_t antenna; - uint8_t pad; -}; - -struct s_lmo_burst { - uint8_t flags; - uint8_t queue; - uint8_t backlog; - uint8_t pad; - uint16_t durations[32]; -}; - -struct s_lmo_stats { - uint32_t valid; - uint32_t fcs; - uint32_t abort; - uint32_t phyabort; - uint32_t rts_success; - uint32_t rts_fail; - uint32_t timestamp; - uint32_t time_tx; - uint32_t noisefloor; - uint32_t sample_noise[8]; - uint32_t sample_cca; - uint32_t sample_tx; -}; - - -struct s_lmo_led { - uint16_t flags; - uint16_t mask[2]; - uint16_t delay/*[2]*/; -}; - - -struct s_lmo_bt_balancer { - uint16_t prio_thresh; - uint16_t acl_thresh; -}; - - -struct s_lmo_arp_table { - uint16_t filter_enable; - uint32_t ipaddr; -}; - -#endif /* __ASSEMBLER__ */ - -#endif /* __lmac_h__ */ diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 7f96bcaf1c60..05186110c029 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -1332,7 +1332,6 @@ device_release_WPADEV(pDevice); free_netdev(pDevice->dev); } - kfree(pDevice); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_disconnect3.. \n"); } diff --git a/drivers/staging/winbond/Kconfig b/drivers/staging/winbond/Kconfig index 940460c39f36..132671d96d0d 100644 --- a/drivers/staging/winbond/Kconfig +++ b/drivers/staging/winbond/Kconfig @@ -1,6 +1,6 @@ config W35UND tristate "IS89C35 WLAN USB driver" - depends on MAC80211 && WLAN_80211 && USB && EXPERIMENTAL + depends on MAC80211 && WLAN && USB && EXPERIMENTAL default n ---help--- This is highly experimental driver for Winbond WIFI card. diff --git a/drivers/staging/wlan-ng/Kconfig b/drivers/staging/wlan-ng/Kconfig index 9959b658c8cf..f44294b0d8dc 100644 --- a/drivers/staging/wlan-ng/Kconfig +++ b/drivers/staging/wlan-ng/Kconfig @@ -1,6 +1,6 @@ config PRISM2_USB tristate "Prism2.5/3 USB driver" - depends on WLAN_80211 && USB && WIRELESS_EXT + depends on WLAN && USB && WIRELESS_EXT default n ---help--- This is the wlan-ng prism 2.5/3 USB driver for a wide range of diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 33351312327f..a18e3c5dd82e 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -223,6 +223,7 @@ config USB_OTG config USB_GADGET_PXA25X boolean "PXA 25x or IXP 4xx" depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX + select USB_OTG_UTILS help Intel's PXA 25x series XScale ARM-5TE processors include an integrated full speed USB 1.1 device controller. The diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 42a74b8a0bb8..fa3d142ba64d 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -2139,7 +2139,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count, static void fsl_udc_release(struct device *dev) { complete(udc_controller->done); - dma_free_coherent(dev, udc_controller->ep_qh_size, + dma_free_coherent(dev->parent, udc_controller->ep_qh_size, udc_controller->ep_qh, udc_controller->ep_qh_dma); kfree(udc_controller); } diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 749b53742828..e33d36256350 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -1003,19 +1003,20 @@ static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port, if (syssts == SE0) { r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port)); r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port)); - return; - } + } else { + if (syssts == FS_JSTS) + r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port)); + else if (syssts == LS_JSTS) + r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port)); - if (syssts == FS_JSTS) - r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port)); - else if (syssts == LS_JSTS) - r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port)); + r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port)); + r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port)); - r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port)); - r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port)); + if (r8a66597->bus_suspended) + usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); + } - if (r8a66597->bus_suspended) - usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); + usb_hcd_poll_rh_status(r8a66597_to_hcd(r8a66597)); } /* this function must be called with interrupt disabled */ @@ -1024,6 +1025,8 @@ static void r8a66597_usb_connect(struct r8a66597 *r8a66597, int port) u16 speed = get_rh_usb_speed(r8a66597, port); struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; + rh->port &= ~((1 << USB_PORT_FEAT_HIGHSPEED) | + (1 << USB_PORT_FEAT_LOWSPEED)); if (speed == HSMODE) rh->port |= (1 << USB_PORT_FEAT_HIGHSPEED); else if (speed == LSMODE) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 65d96b214f95..cd44c68954df 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -315,6 +315,9 @@ static int option_resume(struct usb_serial *serial); #define QISDA_PRODUCT_H20_4515 0x4515 #define QISDA_PRODUCT_H20_4519 0x4519 +/* TLAYTECH PRODUCTS */ +#define TLAYTECH_VENDOR_ID 0x20B9 +#define TLAYTECH_PRODUCT_TEU800 0x1682 /* TOSHIBA PRODUCTS */ #define TOSHIBA_VENDOR_ID 0x0930 @@ -593,6 +596,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) }, { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) }, { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, + { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 45883988a005..5019325ba25d 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -296,7 +296,6 @@ struct sierra_port_private { int dsr_state; int dcd_state; int ri_state; - unsigned int opened:1; }; @@ -306,6 +305,8 @@ static int sierra_send_setup(struct usb_serial_port *port) struct sierra_port_private *portdata; __u16 interface = 0; int val = 0; + int do_send = 0; + int retval; dev_dbg(&port->dev, "%s\n", __func__); @@ -324,10 +325,7 @@ static int sierra_send_setup(struct usb_serial_port *port) */ if (port->interrupt_in_urb) { /* send control message */ - return usb_control_msg(serial->dev, - usb_rcvctrlpipe(serial->dev, 0), - 0x22, 0x21, val, interface, - NULL, 0, USB_CTRL_SET_TIMEOUT); + do_send = 1; } } @@ -339,12 +337,18 @@ static int sierra_send_setup(struct usb_serial_port *port) interface = 1; else if (port->bulk_out_endpointAddress == 5) interface = 2; - return usb_control_msg(serial->dev, - usb_rcvctrlpipe(serial->dev, 0), - 0x22, 0x21, val, interface, - NULL, 0, USB_CTRL_SET_TIMEOUT); + + do_send = 1; } - return 0; + if (!do_send) + return 0; + + usb_autopm_get_interface(serial->interface); + retval = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + 0x22, 0x21, val, interface, NULL, 0, USB_CTRL_SET_TIMEOUT); + usb_autopm_put_interface(serial->interface); + + return retval; } static void sierra_set_termios(struct tty_struct *tty, @@ -773,8 +777,11 @@ static void sierra_close(struct usb_serial_port *port) if (serial->dev) { mutex_lock(&serial->disc_mutex); - if (!serial->disconnected) + if (!serial->disconnected) { + serial->interface->needs_remote_wakeup = 0; + usb_autopm_get_interface(serial->interface); sierra_send_setup(port); + } mutex_unlock(&serial->disc_mutex); spin_lock_irq(&intfdata->susp_lock); portdata->opened = 0; @@ -788,8 +795,6 @@ static void sierra_close(struct usb_serial_port *port) sierra_release_urb(portdata->in_urbs[i]); portdata->in_urbs[i] = NULL; } - usb_autopm_get_interface(serial->interface); - serial->interface->needs_remote_wakeup = 0; } } @@ -827,6 +832,8 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port) if (err) { /* get rid of everything as in close */ sierra_close(port); + /* restore balance for autopm */ + usb_autopm_put_interface(serial->interface); return err; } sierra_send_setup(port); @@ -915,7 +922,7 @@ static void sierra_release(struct usb_serial *serial) #ifdef CONFIG_PM static void stop_read_write_urbs(struct usb_serial *serial) { - int i, j; + int i; struct usb_serial_port *port; struct sierra_port_private *portdata; @@ -923,8 +930,7 @@ static void stop_read_write_urbs(struct usb_serial *serial) for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; portdata = usb_get_serial_port_data(port); - for (j = 0; j < N_IN_URB; j++) - usb_kill_urb(portdata->in_urbs[j]); + sierra_stop_rx_urbs(port); usb_kill_anchored_urbs(&portdata->active); } } diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 4a1f1ebff7bf..28d9cf7cf72f 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -530,19 +530,22 @@ static int vp_try_to_find_vqs(struct virtio_device *vdev, unsigned nvqs, err = PTR_ERR(vqs[i]); goto error_find; } + + if (!vp_dev->per_vq_vectors || msix_vec == VIRTIO_MSI_NO_VECTOR) + continue; + /* allocate per-vq irq if available and necessary */ - if (vp_dev->per_vq_vectors) { - snprintf(vp_dev->msix_names[msix_vec], - sizeof *vp_dev->msix_names, - "%s-%s", - dev_name(&vp_dev->vdev.dev), names[i]); - err = request_irq(msix_vec, vring_interrupt, 0, - vp_dev->msix_names[msix_vec], - vqs[i]); - if (err) { - vp_del_vq(vqs[i]); - goto error_find; - } + snprintf(vp_dev->msix_names[msix_vec], + sizeof *vp_dev->msix_names, + "%s-%s", + dev_name(&vp_dev->vdev.dev), names[i]); + err = request_irq(vp_dev->msix_entries[msix_vec].vector, + vring_interrupt, 0, + vp_dev->msix_names[msix_vec], + vqs[i]); + if (err) { + vp_del_vq(vqs[i]); + goto error_find; } } return 0; diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index f53600580726..fbd2ecde93e4 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -285,6 +285,9 @@ static void *vring_get_buf(struct virtqueue *_vq, unsigned int *len) return NULL; } + /* Only get used array entries after they have been exposed by host. */ + rmb(); + i = vq->vring.used->ring[vq->last_used_idx%vq->vring.num].id; *len = vq->vring.used->ring[vq->last_used_idx%vq->vring.num].len; |