[PATCH] staging: sm750fb: prefix global identifiers
Renaming some symbols inside this driver caused a conflict with an existing function, which in turn results in a link error: drivers/staging/sm750fb/sm750fb.o: In function `enable_dma': ddk750_hwi2c.c:(.text.enable_dma+0x0): multiple definition of `enable_dma' This adds a sm750_ prefix to each global symbol in the sm750fb driver that does not already have one. I manually looked for the symbols and then converted the driver using for i in calc_pll_value format_pll_reg set_power_mode set_current_gate\ enable_2d_engine enable_dma enable_gpio enable_i2c hw_set2dformat \ hw_de_init hw_fillrect hw_copyarea hw_imageblit hw_cursor_enable \ hw_cursor_disable hw_cursor_setSize hw_cursor_setPos \ hw_cursor_setColor hw_cursor_setData hw_cursor_setData2 ; do sed -i "s:\<$i\>:sm750_$i:" drivers/staging/sm750fb/*.[ch] done Fixes: 03140dabf584 ("staging: sm750fb: Replace functions CamelCase naming with underscores.") Signed-off-by: Arnd Bergmann --- drivers/staging/sm750fb/ddk750_chip.c | 24 drivers/staging/sm750fb/ddk750_chip.h | 4 ++-- drivers/staging/sm750fb/ddk750_hwi2c.c | 4 ++-- drivers/staging/sm750fb/ddk750_mode.c | 6 +++--- drivers/staging/sm750fb/ddk750_power.c | 20 ++-- drivers/staging/sm750fb/ddk750_power.h | 12 ++-- drivers/staging/sm750fb/ddk750_swi2c.c | 2 +- drivers/staging/sm750fb/sm750.c| 22 +++--- drivers/staging/sm750fb/sm750_accel.c | 10 +- drivers/staging/sm750fb/sm750_accel.h | 10 +- drivers/staging/sm750fb/sm750_cursor.c | 14 +++--- drivers/staging/sm750fb/sm750_cursor.h | 14 +++--- drivers/staging/sm750fb/sm750_hw.c | 4 ++-- 13 files changed, 73 insertions(+), 73 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 14b5112dfb03..94f59f446322 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -68,16 +68,16 @@ static void set_chip_clock(unsigned int frequency) pll.clockType = MXCLK_PLL; /* -* Call calc_pll_value() to fill the other fields of the PLL +* Call sm750_calc_pll_value() to fill the other fields of the PLL * structure. Sometimes, the chip cannot set up the exact * clock required by the User. -* Return value of calc_pll_value gives the actual possible +* Return value of sm750_calc_pll_value gives the actual possible * clock. */ - ulActualMxClk = calc_pll_value(frequency, &pll); + ulActualMxClk = sm750_calc_pll_value(frequency, &pll); /* Master Clock Control: MXCLK_PLL */ - POKE32(MXCLK_PLL_CTRL, format_pll_reg(&pll)); + POKE32(MXCLK_PLL_CTRL, sm750_format_pll_reg(&pll)); } } @@ -121,7 +121,7 @@ static void set_memory_clock(unsigned int frequency) break; } - set_current_gate(reg); + sm750_set_current_gate(reg); } } @@ -173,7 +173,7 @@ static void set_master_clock(unsigned int frequency) break; } - set_current_gate(reg); + sm750_set_current_gate(reg); } } @@ -215,12 +215,12 @@ int ddk750_init_hw(struct initchip_param *pInitParam) if (pInitParam->powerMode != 0) pInitParam->powerMode = 0; - set_power_mode(pInitParam->powerMode); + sm750_set_power_mode(pInitParam->powerMode); /* Enable display power gate & LOCALMEM power gate*/ reg = PEEK32(CURRENT_GATE); reg |= (CURRENT_GATE_DISPLAY | CURRENT_GATE_LOCALMEM); - set_current_gate(reg); + sm750_set_current_gate(reg); if (sm750_get_chip_type() != SM750LE) { /* set panel pll and graphic mode via mmio_88 */ @@ -261,7 +261,7 @@ int ddk750_init_hw(struct initchip_param *pInitParam) } if (pInitParam->setAllEngOff == 1) { - enable_2d_engine(0); + sm750_enable_2d_engine(0); /* Disable Overlay, if a former application left it on */ reg = PEEK32(VIDEO_DISPLAY_CTRL); @@ -284,7 +284,7 @@ int ddk750_init_hw(struct initchip_param *pInitParam) POKE32(DMA_ABORT_INTERRUPT, reg); /* Disable DMA Power, if a former application left it on */ - enable_dma(0); + sm750_enable_dma(0); } /* We can add more initialization as needed. */ @@ -309,7 +309,7 @@ int ddk750_init_hw(struct initchip_param *pInitParam) * M = {1,...,255} * N = {2,...,15} */ -unsigned int calc_pll_value(unsigned int request_orig, struct pll_value *pll) +unsigned int sm750_calc_pll_value(unsigned int request_orig, str
Re: [lustre-devel] [PATCH] staging: lustre: ldlm: pl_recalc time handling is wrong
On Wednesday, November 9, 2016 3:50:29 AM CET Dilger, Andreas wrote: > On Nov 7, 2016, at 19:47, James Simmons wrote: > > > > The ldlm_pool field pl_recalc_time is set to the current > > monotonic clock value but the interval period is calculated > > with the wall clock. This means the interval period will > > always be far larger than the pl_recalc_period, which is > > just a small interval time period. The correct thing to > > do is to use monotomic clock current value instead of the > > wall clocks value when calculating recalc_interval_sec. > > It looks like this was introduced by commit 8f83409cf > "staging/lustre: use 64-bit time for pl_recalc" but that patch changed > get_seconds() to a mix of ktime_get_seconds() and ktime_get_real_seconds() > for an unknown reason. It doesn't appear that there is any difference > in overhead between the two (on 64-bit at least). It was meant to use ktime_get_real_seconds() consistently, very sorry about the mistake. I don't remember exactly how we got there, I assume I had started out using ktime_get_seconds() and then moved to ktime_get_real_seconds() later but missed the last three instances. > Since the ldlm pool recalculation interval is actually driven in response to > load on the server, it makes sense to use the "real" time instead of the > monotonic time (if I understand correctly) if the client is in a VM that > may periodically be blocked and "miss time" compared to the outside world. > Using the "real" clock, the recalc_interval_sec will correctly reflect the > actual elapsed time rather than just the number of ticks inside the VM. > > Is my understanding of these different clocks correct? No, this is not the difference: monotonic and real time always tick at exactly the same rate, the only difference is the starting point. monotonic time starts at boot and can not be adjusted, while real time is set to reflect the UTC time base and gets initialized from the real time clock at boot, or using settimeofday(2) or NTP later on. In my changelog text, I wrote keeping the 'real' instead of 'monotonic' time because of the debug prints. the intention here is simply to have the console log keep the same numbers as "date +%s" for absolute values. The patch that James suggested converting everything to ktime_get_seconds() would result in the same intervals that have always been there (until I broke it by using time domains inconsistently), but would mean we could use a u32 type for pl_recalc_time and pl_recalc_period because that doesn't overflow until 136 years after booting. (signed time_t overflows 68 years after 1970, i.e 2038). Arnd ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH] staging: vc04_services: rework ioctl code path
VCHIQ/vc04_services has a userland device interface that includes ioctls. The current ioctl implementation is a single monolithic function over 1,000+ lines that handles 17 different ioctls through a complex maze of switch and if statements. The change reimplements that code path by breaking up the code into smaller, easier to maintain functions and uses a dispatch table to invoke the correct function. Testing: 1. vchiq_test -f 10 and vchiq_test -p 1 were run from a native 64-bit OS(debian sid). 2. vchiq_test -f 10 and vchiq_test -p 1 where run from a 32-bit chroot install from the same OS. Both test cases pass. Signed-off-by: Michael Zoran --- .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 1914 +--- .../vc04_services/interface/vchiq_arm/vchiq_if.h | 19 + .../interface/vchiq_arm/vchiq_ioctl.h | 69 + 3 files changed, 1389 insertions(+), 613 deletions(-) diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index 8fcd940..e52a06b 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -503,709 +503,1394 @@ vchiq_ioc_queue_message(VCHIQ_SERVICE_HANDLE_T handle, &context, total_size); } -/ -* -* vchiq_ioctl -* -***/ +static long vchiq_map_status(VCHIQ_STATUS_T status) +{ + if (status == VCHIQ_ERROR) + return -EIO; + + if (status == VCHIQ_RETRY) + return -EINTR; + + return 0; +} + static long -vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +vchiq_ioctl_shutdown(VCHIQ_INSTANCE_T instance, +unsigned int cmd, +unsigned long arg) { + VCHIQ_SERVICE_T *service = NULL; + int i; + + if (!instance->connected) + return 0; + + /* Remove all services */ + i = 0; + while ((service = next_service_by_instance(instance->state, + instance, &i)) != NULL) { + VCHIQ_STATUS_T status; + + status = vchiq_remove_service(service->handle); + unlock_service(service); + + if (status != VCHIQ_SUCCESS) + return vchiq_map_status(status); + } + + /* Wake the completion thread and ask it to exit */ + instance->closing = 1; + up(&instance->insert_event); + + return 0; +} + +static long +vchiq_ioctl_connect(VCHIQ_INSTANCE_T instance, + unsigned int cmd, + unsigned long arg) { - VCHIQ_INSTANCE_T instance = file->private_data; VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + int rc; + + if (instance->connected) + return -EINVAL; + + rc = mutex_lock_interruptible(&instance->state->mutex); + if (rc) { + vchiq_log_error(vchiq_arm_log_level, + "vchiq: connect: could not lock mutex for state %d: %d", + instance->state->id, rc); + return -EINTR; + } + + status = vchiq_connect_internal(instance->state, instance); + mutex_unlock(&instance->state->mutex); + + if (status != VCHIQ_SUCCESS) { + vchiq_log_error(vchiq_arm_log_level, + "vchiq: could not connect: %d", status); + return vchiq_map_status(status); + } + + instance->connected = 1; + return 0; +} + +static long +vchiq_ioctl_create_service_internal(VCHIQ_INSTANCE_T instance, + VCHIQ_CREATE_SERVICE_T *args) +{ + VCHIQ_SERVICE_T *service = NULL; + USER_SERVICE_T *user_service = NULL; + void *userdata; + VCHIQ_STATUS_T status = VCHIQ_SUCCESS; + int srvstate; + + user_service = kmalloc(sizeof(USER_SERVICE_T), GFP_KERNEL); + if (!user_service) + return -ENOMEM; + + if (args->is_open) { + if (!instance->connected) { + kfree(user_service); + return -ENOTCONN; + } + srvstate = VCHIQ_SRVSTATE_OPENING; + } else { + srvstate = + instance->connected ? + VCHIQ_SRVSTATE_LISTENING : + VCHIQ_SRVSTATE_HIDDEN; + } + + userdata = args->params.userdata; + args->params.callback = service_callback; + args->params.userdata = user_service; + service = vchiq_add_service_internal( + instance->state, + &args->params, srvstate, + instance, user_service_free); + + if (!service) { + kfree(user_service); +
Re: [PATCH] staging: vc04_services: rework ioctl code path
On Wednesday, November 9, 2016 12:37:27 PM CET Michael Zoran wrote: > static long > -vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) > +vchiq_ioctl_shutdown(VCHIQ_INSTANCE_T instance, > + unsigned int cmd, > + unsigned long arg) { This does not use cmd or arg, so you can just drop both parameters. In cases where the argument is actually used, better make it take a pointer than an unsigned long argument, to save a conversion. > + vchiq_log_trace(vchiq_arm_log_level, > + "vchiq_ioctl(compat) - instance %pK, cmd %s, arg %lx", > + instance, > + ((_IOC_TYPE(cmd) == VCHIQ_IOC_MAGIC) && > + (ioctl_nr <= VCHIQ_IOC_MAX)) ? > + ioctl_names[ioctl_nr] : "", arg); I'd suggest dropping the log_trace here. > + if ((ioctl_nr > VCHIQ_IOC_MAX) || > + (vchiq_ioctl_compat_table[ioctl_nr].ioctl != cmd)) { > + ret = -ENOTTY; > + } else { > + ret = vchiq_ioctl_compat_table[ioctl_nr].func(instance, cmd, > arg); > } It's rather unusual to have a table like this, most drivers have a simple switch/case statement. If you do a swapper like this, better make it do something more and let it also pass the data as a kernel pointer that you copy in and out of the kernel according to the direction and size bits in the command number. > @@ -104,6 +109,12 @@ typedef struct vchiq_service_base_struct { > void *userdata; > } VCHIQ_SERVICE_BASE_T; > > +struct vchiq_service_base32 { > + int fourcc; > + u32 callback; > + u32 userdata; > +}; Maybe better use compat_uptr_t along with compat_ptr() for passing 32-bit pointers. This will however require moving the struct definitions into an #ifdef. Arnd ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
RE: [PATCH 8/9] bus: fsl-mc: dpio: add the DPAA2 DPIO object driver
> -Original Message- > From: Ruxandra Ioana Radulescu > Sent: Friday, November 04, 2016 10:11 AM > To: Stuart Yoder ; gre...@linuxfoundation.org > Cc: German Rivera ; de...@driverdev.osuosl.org; > linux-ker...@vger.kernel.org; > ag...@suse.de; a...@arndb.de; Leo Li ; Roy Pledge > ; Haiying Wang > ; Stuart Yoder > Subject: RE: [PATCH 8/9] bus: fsl-mc: dpio: add the DPAA2 DPIO object driver > > > -Original Message- > > From: Stuart Yoder > > Sent: Thursday, November 03, 2016 4:38 PM > > To: Ruxandra Ioana Radulescu > > Subject: FW: [PATCH 8/9] bus: fsl-mc: dpio: add the DPAA2 DPIO object > > driver > > > > > > > > -Original Message- > > From: Stuart Yoder [mailto:stuart.yo...@nxp.com] > > Sent: Friday, October 21, 2016 9:02 AM > > To: gre...@linuxfoundation.org > > Cc: German Rivera ; de...@driverdev.osuosl.org; > > linux-ker...@vger.kernel.org; ag...@suse.de; a...@arndb.de; Leo Li > > ; Roy Pledge ; Haiying Wang > > ; Stuart Yoder > > Subject: [PATCH 8/9] bus: fsl-mc: dpio: add the DPAA2 DPIO object driver > > > > From: Roy Pledge > > > > The DPIO driver registers with the fsl-mc bus to handle bus-related > > events for DPIO objects. Key responsibility is mapping I/O > > regions, setting up interrupt handlers, and calling the DPIO > > service initialization during probe. > > > > Signed-off-by: Roy Pledge > > Signed-off-by: Haiying Wang > > Signed-off-by: Stuart Yoder > > --- > > drivers/bus/fsl-mc/dpio/Makefile | 2 +- > > drivers/bus/fsl-mc/dpio/dpio-driver.c | 289 > > ++ > > 2 files changed, 290 insertions(+), 1 deletion(-) > > create mode 100644 drivers/bus/fsl-mc/dpio/dpio-driver.c > > > > diff --git a/drivers/bus/fsl-mc/dpio/Makefile b/drivers/bus/fsl- > > mc/dpio/Makefile > > index 0778da7..837d330 100644 > > --- a/drivers/bus/fsl-mc/dpio/Makefile > > +++ b/drivers/bus/fsl-mc/dpio/Makefile > > @@ -6,4 +6,4 @@ subdir-ccflags-y := -Werror > > > > obj-$(CONFIG_FSL_MC_DPIO) += fsl-mc-dpio.o > > > > -fsl-mc-dpio-objs := dpio.o qbman-portal.o dpio-service.o > > +fsl-mc-dpio-objs := dpio.o qbman-portal.o dpio-service.o dpio-driver.o > > diff --git a/drivers/bus/fsl-mc/dpio/dpio-driver.c b/drivers/bus/fsl- > > mc/dpio/dpio-driver.c > > new file mode 100644 > > index 000..ad04a2c > > --- /dev/null > > +++ b/drivers/bus/fsl-mc/dpio/dpio-driver.c > > @@ -0,0 +1,289 @@ > > +/* > > + * Copyright 2014-2016 Freescale Semiconductor Inc. > > + * > > + * Redistribution and use in source and binary forms, with or without > > + * modification, are permitted provided that the following conditions are > > met: > > + * * Redistributions of source code must retain the above copyright > > + * notice, this list of conditions and the following disclaimer. > > + * * Redistributions in binary form must reproduce the above copyright > > + * notice, this list of conditions and the following disclaimer in the > > + * documentation and/or other materials provided with the > > distribution. > > + * * Neither the name of Freescale Semiconductor nor the > > + * names of its contributors may be used to endorse or promote > > products > > + * derived from this software without specific prior written permission. > > + * > > + * ALTERNATIVELY, this software may be distributed under the terms of the > > + * GNU General Public License ("GPL") as published by the Free Software > > + * Foundation, either version 2 of that License or (at your option) any > > + * later version. > > + * > > + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND > > ANY > > + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, > > THE IMPLIED > > + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR > > PURPOSE ARE > > + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR > > ANY > > + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR > > CONSEQUENTIAL DAMAGES > > + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE > > GOODS OR SERVICES; > > + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > > HOWEVER CAUSED AND > > + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, > > OR TORT > > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF > > THE USE OF THIS > > + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > +#include > > + > > +#include "qbman-portal.h" > > +#include "dpio.h" > > +#include "dpio-cmd.h" > > + > > +MODULE_LICENSE("Dual BSD/GPL"); > > +MODULE_AUTHOR("Freescale Semiconductor, Inc"); > > +MODULE_DESCRIPTION("DPIO Driver"); > > + > > +struct dpio_priv { > > + struct dpaa2_io *io; > > +}; > > + > > +static irqreturn_t dpio_irq_handler(int irq_num, void *arg) > > +{ > > + struct device *dev = (struct device *)arg; > > + struct dpio_priv *priv = dev_get_drvdata(dev);
[PATCH 0/3] PCI: hv: clean-up and 2 fixes to the hot-remove case
PATCH 1 is just a clean-up. There should be no functional change. PATCH 2 and 3 are for device hot-remove case. Currently the driver will stop working or even cause panic, if we do hot add/remove quickly a few times. With the 2 patches, everything works reliably in my tests now. There can be still a potential issue with hot-remove when we unload the driver at the same time. That would require more work of proper synchronization among the 3 paths: the .probe/.remove, the channel callback, and the offloaded hv_pci_devices_present()/hv_eject_device_work(). But for now, PATCH 2 and 3 do improve the situation a lot. Dexuan Cui (3): PCI: hv: use the correct buffer size in new_pcichild_device() PCI: hv: fix hv_pci_remove() for hot-remove PCI: hv: delete the device earlier from hbus->children for hot-remove drivers/pci/host/pci-hyperv.c | 67 ++- 1 file changed, 40 insertions(+), 27 deletions(-) -- 2.7.4 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 1/3] PCI: hv: use the correct buffer size in new_pcichild_device()
We don't really need such a big on-stack buffer. vmbus_sendpacket() here only uses sizeof(struct pci_child_message). Signed-off-by: Dexuan Cui CC: Jake Oshins Cc: KY Srinivasan CC: Haiyang Zhang CC: Vitaly Kuznetsov --- drivers/pci/host/pci-hyperv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c index 763ff87..93ed64a 100644 --- a/drivers/pci/host/pci-hyperv.c +++ b/drivers/pci/host/pci-hyperv.c @@ -1271,9 +1271,9 @@ static struct hv_pci_dev *new_pcichild_device(struct hv_pcibus_device *hbus, struct hv_pci_dev *hpdev; struct pci_child_message *res_req; struct q_res_req_compl comp_pkt; - union { - struct pci_packet init_packet; - u8 buffer[0x100]; + struct { + struct pci_packet init_packet; + u8 buffer[sizeof(struct pci_child_message)]; } pkt; unsigned long flags; int ret; -- 2.7.4 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 2/3] PCI: hv: fix hv_pci_remove() for hot-remove
1. We don't really need such a big on-stack buffer when sending the teardown_packet: vmbus_sendpacket() here only uses sizeof(struct pci_message). 2. In the hot-remove case (PCI_EJECT), after we send PCI_EJECTION_COMPLETE to the host, the host will send a RESCIND_CHANNEL message to us and the host won't access the per-channel ringbuffer any longer, so we needn't send PCI_RESOURCES_RELEASED/PCI_BUS_D0EXIT to the host, and we shouldn't expect the host's completion message of PCI_BUS_D0EXIT, which will never come. 3. We should send PCI_BUS_D0EXIT after hv_send_resources_released(). Signed-off-by: Dexuan Cui CC: Jake Oshins Cc: KY Srinivasan CC: Haiyang Zhang CC: Vitaly Kuznetsov --- I made the patch based on discussions with Jake Oshins and others. drivers/pci/host/pci-hyperv.c | 53 +++ 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c index 93ed64a..7590ad0 100644 --- a/drivers/pci/host/pci-hyperv.c +++ b/drivers/pci/host/pci-hyperv.c @@ -2266,24 +2266,32 @@ static int hv_pci_probe(struct hv_device *hdev, return ret; } -/** - * hv_pci_remove() - Remove routine for this VMBus channel - * @hdev: VMBus's tracking struct for this root PCI bus - * - * Return: 0 on success, -errno on failure - */ -static int hv_pci_remove(struct hv_device *hdev) +static void hv_pci_bus_exit(struct hv_device *hdev) { - int ret; - struct hv_pcibus_device *hbus; - union { + struct hv_pcibus_device *hbus = hv_get_drvdata(hdev); + struct { struct pci_packet teardown_packet; - u8 buffer[0x100]; + u8 buffer[sizeof(struct pci_message)]; } pkt; struct pci_bus_relations relations; struct hv_pci_compl comp_pkt; + int ret; - hbus = hv_get_drvdata(hdev); + /* +* After the host sends the RESCIND_CHANNEL message, it doesn't +* access the per-channel ringbuffer any longer. +*/ + if (hdev->channel->rescind) + return; + + /* Delete any children which might still exist. */ + memset(&relations, 0, sizeof(relations)); + hv_pci_devices_present(hbus, &relations); + + ret = hv_send_resources_released(hdev); + if (ret) + dev_err(&hdev->device, + "Couldn't send resources released packet(s)\n"); memset(&pkt.teardown_packet, 0, sizeof(pkt.teardown_packet)); init_completion(&comp_pkt.host_event); @@ -2298,7 +2306,19 @@ static int hv_pci_remove(struct hv_device *hdev) VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (!ret) wait_for_completion_timeout(&comp_pkt.host_event, 10 * HZ); +} + +/** + * hv_pci_remove() - Remove routine for this VMBus channel + * @hdev: VMBus's tracking struct for this root PCI bus + * + * Return: 0 on success, -errno on failure + */ +static int hv_pci_remove(struct hv_device *hdev) +{ + struct hv_pcibus_device *hbus; + hbus = hv_get_drvdata(hdev); if (hbus->state == hv_pcibus_installed) { /* Remove the bus from PCI's point of view. */ pci_lock_rescan_remove(); @@ -2307,17 +2327,10 @@ static int hv_pci_remove(struct hv_device *hdev) pci_unlock_rescan_remove(); } - ret = hv_send_resources_released(hdev); - if (ret) - dev_err(&hdev->device, - "Couldn't send resources released packet(s)\n"); + hv_pci_bus_exit(hdev); vmbus_close(hdev->channel); - /* Delete any children which might still exist. */ - memset(&relations, 0, sizeof(relations)); - hv_pci_devices_present(hbus, &relations); - iounmap(hbus->cfg_addr); hv_free_config_window(hbus); pci_free_resource_list(&hbus->resources_for_children); -- 2.7.4 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 3/3] PCI: hv: delete the device earlier from hbus->children for hot-remove
After we send a PCI_EJECTION_COMPLETE message to the host, the host will immediately send us a PCI_BUS_RELATIONS message with relations->device_count == 0, so pci_devices_present_work(), running on another thread, can find the being-ejected device, mark the hpdev->reported_missing to true, and run list_move_tail()/list_del() for the device -- this races hv_eject_device_work() -> list_del(). The patch moves the list_del() in hv_eject_device_work() to an earlier place, i.e. before we send PCI_EJECTION_COMPLETE, so later the pci_devices_present_work() can't see the device. Signed-off-by: Dexuan Cui CC: Jake Oshins Cc: KY Srinivasan CC: Haiyang Zhang CC: Vitaly Kuznetsov --- drivers/pci/host/pci-hyperv.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c index 7590ad0..fe5179d 100644 --- a/drivers/pci/host/pci-hyperv.c +++ b/drivers/pci/host/pci-hyperv.c @@ -1582,6 +1582,10 @@ static void hv_eject_device_work(struct work_struct *work) pci_dev_put(pdev); } + spin_lock_irqsave(&hpdev->hbus->device_list_lock, flags); + list_del(&hpdev->list_entry); + spin_unlock_irqrestore(&hpdev->hbus->device_list_lock, flags); + memset(&ctxt, 0, sizeof(ctxt)); ejct_pkt = (struct pci_eject_response *)&ctxt.pkt.message; ejct_pkt->message_type.type = PCI_EJECTION_COMPLETE; @@ -1590,10 +1594,6 @@ static void hv_eject_device_work(struct work_struct *work) sizeof(*ejct_pkt), (unsigned long)&ctxt.pkt, VM_PKT_DATA_INBAND, 0); - spin_lock_irqsave(&hpdev->hbus->device_list_lock, flags); - list_del(&hpdev->list_entry); - spin_unlock_irqrestore(&hpdev->hbus->device_list_lock, flags); - put_pcichild(hpdev, hv_pcidev_ref_childlist); put_pcichild(hpdev, hv_pcidev_ref_pnp); put_hvpcibus(hpdev->hbus); -- 2.7.4 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel