Exemple #1
0
static ssize_t recover_store(struct device *dev, struct device_attribute *attr,
			     const char *buf, size_t count)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	struct zpci_dev *zdev = to_zpci(pdev);
	int ret;

	if (!device_remove_file_self(dev, attr))
		return count;

	pci_lock_rescan_remove();
	pci_stop_and_remove_bus_device(pdev);
	ret = zpci_disable_device(zdev);
	if (ret)
		goto error;

	ret = zpci_enable_device(zdev);
	if (ret)
		goto error;

	pci_rescan_bus(zdev->bus);
	pci_unlock_rescan_remove();

	return count;

error:
	pci_unlock_rescan_remove();
	return ret;
}
Exemple #2
0
void zpci_event_availability(void *data)
{
    struct zpci_ccdf_avail *ccdf = data;
    struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
    struct pci_dev *pdev = zdev ? zdev->pdev : NULL;
    int ret;

    pr_info("%s: Event 0x%x reconfigured PCI function 0x%x\n",
            pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid);
    zpci_err("avail CCDF:\n");
    zpci_err_hex(ccdf, sizeof(*ccdf));

    switch (ccdf->pec) {
    case 0x0301: /* Standby -> Configured */
        if (!zdev || zdev->state == ZPCI_FN_STATE_CONFIGURED)
            break;
        zdev->state = ZPCI_FN_STATE_CONFIGURED;
        ret = zpci_enable_device(zdev);
        if (ret)
            break;
        pci_rescan_bus(zdev->bus);
        break;
    case 0x0302: /* Reserved -> Standby */
        clp_add_pci_device(ccdf->fid, ccdf->fh, 0);
        break;
    case 0x0303: /* Deconfiguration requested */
        if (pdev)
            pci_stop_and_remove_bus_device(pdev);

        ret = zpci_disable_device(zdev);
        if (ret)
            break;

        ret = sclp_pci_deconfigure(zdev->fid);
        zpci_dbg(3, "deconf fid:%x, rc:%d\n", zdev->fid, ret);
        if (!ret)
            zdev->state = ZPCI_FN_STATE_STANDBY;

        break;
    case 0x0304: /* Configured -> Standby */
        if (pdev)
            pci_stop_and_remove_bus_device(pdev);

        zpci_disable_device(zdev);
        zdev->state = ZPCI_FN_STATE_STANDBY;
        break;
    case 0x0306: /* 0x308 or 0x302 for multiple devices */
        clp_rescan_pci_devices();
        break;
    case 0x0308: /* Standby -> Reserved */
        pci_stop_root_bus(zdev->bus);
        pci_remove_root_bus(zdev->bus);
        break;
    default:
        break;
    }
}
Exemple #3
0
/*
 * test_scan_bus
 *	call to pci_do_scan_bus,  which takes
 *	a struct pci_bus pointer, which will
 *	return an integer for how far the
 *	function got in scanning bus
 */
static int test_scan_bus(void)
{
#ifdef CONFIG_HOTPLUG
	int num;
	struct pci_bus *bus = ltp_pci.bus;

	prk_info("scan pci bus");

	num = pci_rescan_bus(bus);
	/*
	 * check if returned number is greater than
	 * max number of bus or less than 0
	 */
	if (num > MAX_BUS || num < 0) {
		prk_err("failed scan bus");
		return TFAIL;
	}
	prk_info("success scan bus");
	return TPASS;
#else
	prk_info("pci_rescan_bus() is not supported");
	return TSKIP;
#endif
}
int pcie_wifi_pwrctrl_restore(void)
{
    int ret = 0;

    ret = regulator_enable(pcie_regulator);
    if (ret)
    {
        printk(KERN_ERR "fail to enable regulator\n");
        return ret;
    }

    pcie_wifi_poweron();
#if !defined(BSP_CONFIG_V7R2_SFT)
    pcie_clk_enable();
    pcie_phy_ctrl_reset();
    pcie_phy_ctrl_undo_reset();
#endif
    enable_irq(INT_LVL_PCIE0_LINK_DOWN);
    pcie_hw_preinit();
    pcie_ltssm_enable(true);
    ret = pcie_link_up_confirm();
    if(-EIO == ret)
    {
        goto out;
    }
    pcie_hw_postinit();
    pci_rescan_bus(root_bus);

    pcie_port_dev = pci_get_class((PCI_CLASS_BRIDGE_PCI << 8), NULL);
    if(!pcie_port_dev)
    {
        printk(KERN_ERR "bridge not found,please check.\n");
        return -EIO;
    }
    pcie_wifi_dev = pci_get_subsys(WIFI_VENDOR_ID,WIFI_DEVICE_ID,
                                   WIFI_SS_VENDOR_ID,WIFI_SS_ID,NULL);
    if(!pcie_wifi_dev)
    {
        printk(KERN_ERR "wifi dev not found,please check.\n");
        return -EIO;
    }

    /*recover interrupt pin&line*/
    pci_write_config_byte(pcie_port_dev,PCI_INTERRUPT_PIN,pcie_port_dev_int_pin);
    pci_write_config_byte(pcie_wifi_dev,PCI_INTERRUPT_PIN,pcie_wifi_dev_int_pin);
    pcie_port_dev->pin = pcie_port_dev_int_pin;
    pcie_port_dev->irq = pcie_port_dev_int_irq;
    pcie_wifi_dev->pin = pcie_wifi_dev_int_pin;
    pcie_wifi_dev->irq = pcie_wifi_dev_int_irq;
    pcibios_update_irq(pcie_port_dev,pcie_port_dev_int_irq);
    pcibios_update_irq(pcie_wifi_dev,pcie_wifi_dev_int_irq);

    ret = pcie_port_bus_register();
	if (ret) {
		printk(KERN_WARNING "PCIE: bus_register error: %d\n", ret);
		goto out;
	}
    ret = pci_register_driver(&pcie_portdriver);
	if (ret)
	{
		pcie_port_bus_unregister();
	}
 out:
	return ret;
}
Exemple #5
0
static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
{
	struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
	struct pci_dev *pdev = NULL;
	int ret;

	if (zdev)
		pdev = pci_get_slot(zdev->bus, ZPCI_DEVFN);

	pr_info("%s: Event 0x%x reconfigured PCI function 0x%x\n",
		pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid);
	zpci_err("avail CCDF:\n");
	zpci_err_hex(ccdf, sizeof(*ccdf));

	switch (ccdf->pec) {
	case 0x0301: /* Reserved|Standby -> Configured */
		if (!zdev) {
			ret = clp_add_pci_device(ccdf->fid, ccdf->fh, 0);
			if (ret)
				break;
			zdev = get_zdev_by_fid(ccdf->fid);
		}
		if (!zdev || zdev->state != ZPCI_FN_STATE_STANDBY)
			break;
		zdev->state = ZPCI_FN_STATE_CONFIGURED;
		zdev->fh = ccdf->fh;
		ret = zpci_enable_device(zdev);
		if (ret)
			break;
		pci_lock_rescan_remove();
		pci_rescan_bus(zdev->bus);
		pci_unlock_rescan_remove();
		break;
	case 0x0302: /* Reserved -> Standby */
		if (!zdev)
			clp_add_pci_device(ccdf->fid, ccdf->fh, 0);
		break;
	case 0x0303: /* Deconfiguration requested */
		if (pdev)
			pci_stop_and_remove_bus_device_locked(pdev);

		ret = zpci_disable_device(zdev);
		if (ret)
			break;

		ret = sclp_pci_deconfigure(zdev->fid);
		zpci_dbg(3, "deconf fid:%x, rc:%d\n", zdev->fid, ret);
		if (!ret)
			zdev->state = ZPCI_FN_STATE_STANDBY;

		break;
	case 0x0304: /* Configured -> Standby */
		if (pdev) {
			/* Give the driver a hint that the function is
			 * already unusable. */
			pdev->error_state = pci_channel_io_perm_failure;
			pci_stop_and_remove_bus_device_locked(pdev);
		}

		zdev->fh = ccdf->fh;
		zpci_disable_device(zdev);
		zdev->state = ZPCI_FN_STATE_STANDBY;
		break;
	case 0x0306: /* 0x308 or 0x302 for multiple devices */
		clp_rescan_pci_devices();
		break;
	case 0x0308: /* Standby -> Reserved */
		if (!zdev)
			break;
		pci_stop_root_bus(zdev->bus);
		pci_remove_root_bus(zdev->bus);
		break;
	default:
		break;
	}
	if (pdev)
		pci_dev_put(pdev);
}
/**
 * do_add
 *
 * Prepares a PCI hot plug slot for adding an adapter, then
 * configures the adapter and any PCI adapters below into
 * the Open Firmware device tree.
 *
 * Verifies that a given hot plug PCI slot does not have an adapter
 * already connected, identifies the slot to the user unless requested not
 * to with the -i flag, prompts the user to connect the adapter, powers
 * the slot on, and calls configure connector. When configure connector
 * completes and returns the new node(s) for the new PCI adapter and any
 * attached devices then the Open Firmware device tree is
 * updated to reflect the new devices.
 */
static int
do_add(struct options *opts, struct dr_node *all_nodes)
{
	struct dr_node *node;
	int usr_key = USER_CONT;
	int rc;

	node = find_slot(opts->usr_drc_name, all_nodes);
	if (node == NULL)
		return -1;

	/* Prompt user only if in interactive mode. */
	if (0 == opts->noprompt) {
		if (!opts->no_ident)
			usr_key = identify_slot(node);

		if (usr_key == USER_QUIT) {
			if (node->children == NULL)
				process_led(node, LED_OFF);
			else
				process_led(node, LED_ON);
			return 0;
		}
	}

	if (node->children != NULL) {
		/* If there's already something here, turn the
		 * LED on and exit with user error.
		 */
		process_led(node, LED_ON);
		say(ERROR, "The specified PCI slot is already occupied.\n");
		return -1;
	}


	/* Now it's time to isolate, power off, set the
	 * action LED, and prompt the user to put the
	 * card in.
	 */

	say(DEBUG, "is calling rtas_set_indicator(ISOLATE index 0x%x)\n",
	    node->drc_index);

	rc = rtas_set_indicator(ISOLATION_STATE, node->drc_index, ISOLATE);
	if (rc) {
		if (rc == HW_ERROR)
			say(ERROR, "%s", hw_error);
		else
			say(ERROR, "%s", sw_error);

		set_power(node->drc_power, POWER_OFF);
		return -1;
	}

	say(DEBUG, "is calling set_power(POWER_OFF index 0x%x, "
	    "power_domain 0x%x) \n", node->drc_index, node->drc_power);

	rc = set_power(node->drc_power, POWER_OFF);
	if (rc) {
		if (rc == HW_ERROR)
			say(ERROR, "%s", hw_error);
		else
			say(ERROR, "%s", sw_error);

		return -1;
	}

	if (0 == opts->noprompt) {
		/* Prompt user to put in card and to press
		 * Enter to continue or other key to exit.
		 */
		if (process_led(node, LED_ACTION))
			return -1;

		printf("The visual indicator for the specified PCI slot has\n"
			"been set to the action state. Insert the PCI card\n"
			"into the identified slot, connect any devices to be\n"
			"configured and press Enter to continue. Enter x to "
			"exit.\n");

		if (!(getchar() == '\n')) {
			process_led(node, LED_OFF);
			return 0;
		}
	}

	/* Call the routine which determines
	 * what the user wants and does it.
	 */
	rc = add_work(opts, node);
	if (rc)
		return rc;

	say(DEBUG, "is calling enable_slot to config adapter\n");

	/* Try to config the adapter. The rpaphp module doesn't play well with
	 * qemu pci slots so we let the generic kernel pci code probe the device
	 * by rescanning the bus in the qemu virtio case.
	 */
	if (!opts->pci_virtio)
		set_hp_adapter_status(PHP_CONFIG_ADAPTER, node->drc_name);
	else
		pci_rescan_bus();

	return 0;
}
Exemple #7
0
/*===========================================================================*
 *				do_int					     *
 *===========================================================================*/
static void do_int(struct port *pp)
{
    int devind, vcc_5v, vcc_3v, vcc_Xv, vcc_Yv,
        socket_5v, socket_3v, socket_Xv, socket_Yv;
    spin_t spin;
    u32_t csr_event, csr_present, csr_control;
    u8_t v8;
    u16_t v16;
#if USE_INTS
    int r;
#endif

    devind= pp->p_devind;
    v8= pci_attr_r8(devind, TI_CARD_CTRL);
    if (v8 & TI_CCR_IFG)
    {
        printf("ti1225: got functional interrupt\n");
        pci_attr_w8(devind, TI_CARD_CTRL, v8);
    }

    if (debug)
    {
        printf("Socket event: 0x%x\n", pp->csr_ptr->csr_event);
        printf("Socket mask: 0x%x\n", pp->csr_ptr->csr_mask);
    }

    csr_present= pp->csr_ptr->csr_present;
    csr_control= pp->csr_ptr->csr_control;

    if ((csr_present & (CP_CDETECT1|CP_CDETECT2)) != 0)
    {
        if (debug)
            printf("do_int: no card present\n");
        return;
    }
    if (csr_present & CP_BADVCCREQ)
    {
        printf("do_int: Bad Vcc request\n");
        /* return; */
    }
    if (csr_present & CP_DATALOST)
    {
        /* Do we care? */
        if (debug)
            printf("do_int: Data lost\n");
        /* return; */
    }
    if (csr_present & CP_NOTACARD)
    {
        printf("do_int: Not a card\n");
        return;
    }
    if (debug)
    {
        if (csr_present & CP_CBCARD)
            printf("do_int: Cardbus card detected\n");
        if (csr_present & CP_16BITCARD)
            printf("do_int: 16-bit card detected\n");
    }
    if (csr_present & CP_PWRCYCLE)
    {
        if (debug)
            printf("do_int: powered up\n");
        return;
    }
    vcc_5v= !!(csr_present & CP_5VCARD);
    vcc_3v= !!(csr_present & CP_3VCARD);
    vcc_Xv= !!(csr_present & CP_XVCARD);
    vcc_Yv= !!(csr_present & CP_YVCARD);
    if (debug)
    {
        printf("do_int: card supports:%s%s%s%s\n",
               vcc_5v ? " 5V" : "", vcc_3v ? " 3V" : "",
               vcc_Xv ? " X.X V" : "", vcc_Yv ? " Y.Y V" : "");
    }
    socket_5v= !!(csr_present & CP_5VSOCKET);
    socket_3v= !!(csr_present & CP_3VSOCKET);
    socket_Xv= !!(csr_present & CP_XVSOCKET);
    socket_Yv= !!(csr_present & CP_YVSOCKET);
    if (debug)
    {
        printf("do_int: socket supports:%s%s%s%s\n",
               socket_5v ? " 5V" : "", socket_3v ? " 3V" : "",
               socket_Xv ? " X.X V" : "", socket_Yv ? " Y.Y V" : "");
    }
    if (vcc_5v && socket_5v)
    {
        csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_5V;
        pp->csr_ptr->csr_control= csr_control;
        if (debug)
            printf("do_int: applying 5V\n");
    }
    else if (vcc_3v && socket_3v)
    {
        csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_3V;
        pp->csr_ptr->csr_control= csr_control;
        if (debug)
            printf("do_int: applying 3V\n");
    }
    else if (vcc_Xv && socket_Xv)
    {
        csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_XV;
        pp->csr_ptr->csr_control= csr_control;
        printf("do_int: applying X.X V\n");
    }
    else if (vcc_Yv && socket_Yv)
    {
        csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_YV;
        pp->csr_ptr->csr_control= csr_control;
        printf("do_int: applying Y.Y V\n");
    }
    else
    {
        printf("do_int: socket and card are not compatible\n");
        return;
    }

    csr_event= pp->csr_ptr->csr_event;
    if (csr_event)
    {
        if (debug)
            printf("clearing socket event\n");
        pp->csr_ptr->csr_event= csr_event;
        if (debug)
        {
            printf("Socket event (cleared): 0x%x\n",
                   pp->csr_ptr->csr_event);
        }
    }

    devind= pp->p_devind;
    v8= pci_attr_r8(devind, TI_CARD_CTRL);
    if (v8 & TI_CCR_IFG)
    {
        printf("ti1225: got functional interrupt\n");
        pci_attr_w8(devind, TI_CARD_CTRL, v8);
    }

    if (debug)
    {
        v8= pci_attr_r8(devind, TI_CARD_CTRL);
        printf("TI_CARD_CTRL: 0x%02x\n", v8);
    }

    spin_init(&spin, 100000);
    do {
        csr_present= pp->csr_ptr->csr_present;
        if (csr_present & CP_PWRCYCLE)
            break;
    } while (spin_check(&spin));

    if (!(csr_present & CP_PWRCYCLE))
    {
        printf("do_int: not powered up?\n");
        return;
    }

    /* Reset device */
    v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
    v16 |= CBB_BC_CRST;
    pci_attr_w16(devind, CBB_BRIDGECTRL, v16);

    /* Wait one microsecond. Is this correct? What are the specs? */
    micro_delay(1);

    /* Clear CBB_BC_CRST */
    v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
    v16 &= ~CBB_BC_CRST;
    pci_attr_w16(devind, CBB_BRIDGECTRL, v16);

    /* Wait one microsecond after clearing the reset line. Is this
     * correct? What are the specs?
     */
    micro_delay(1);

    pci_rescan_bus(pp->p_cb_busnr);

#if USE_INTS
    r= sys_irqenable(&pp->p_hook);
    if (r != OK)
        panic("unable enable interrupts: %d", r);
#endif

}