static int vub300_probe()

in host/vub300.c [2080:2347]


static int vub300_probe(struct usb_interface *interface,
			const struct usb_device_id *id)
{				/* NOT irq */
	struct vub300_mmc_host *vub300;
	struct usb_host_interface *iface_desc;
	struct usb_device *udev = usb_get_dev(interface_to_usbdev(interface));
	int i;
	int retval = -ENOMEM;
	struct urb *command_out_urb;
	struct urb *command_res_urb;
	struct mmc_host *mmc;
	char manufacturer[48];
	char product[32];
	char serial_number[32];
	usb_string(udev, udev->descriptor.iManufacturer, manufacturer,
		   sizeof(manufacturer));
	usb_string(udev, udev->descriptor.iProduct, product, sizeof(product));
	usb_string(udev, udev->descriptor.iSerialNumber, serial_number,
		   sizeof(serial_number));
	dev_info(&udev->dev, "probing VID:PID(%04X:%04X) %s %s %s\n",
		 le16_to_cpu(udev->descriptor.idVendor),
		 le16_to_cpu(udev->descriptor.idProduct),
		 manufacturer, product, serial_number);
	command_out_urb = usb_alloc_urb(0, GFP_KERNEL);
	if (!command_out_urb) {
		retval = -ENOMEM;
		goto error0;
	}
	command_res_urb = usb_alloc_urb(0, GFP_KERNEL);
	if (!command_res_urb) {
		retval = -ENOMEM;
		goto error1;
	}
	/* this also allocates memory for our VUB300 mmc host device */
	mmc = mmc_alloc_host(sizeof(struct vub300_mmc_host), &udev->dev);
	if (!mmc) {
		retval = -ENOMEM;
		dev_err(&udev->dev, "not enough memory for the mmc_host\n");
		goto error4;
	}
	/* MMC core transfer sizes tunable parameters */
	mmc->caps = 0;
	if (!force_1_bit_data_xfers)
		mmc->caps |= MMC_CAP_4_BIT_DATA;
	if (!force_polling_for_irqs)
		mmc->caps |= MMC_CAP_SDIO_IRQ;
	mmc->caps &= ~MMC_CAP_NEEDS_POLL;
	/*
	 * MMC_CAP_NEEDS_POLL causes core.c:mmc_rescan() to poll
	 * for devices which results in spurious CMD7's being
	 * issued which stops some SDIO cards from working
	 */
	if (limit_speed_to_24_MHz) {
		mmc->caps |= MMC_CAP_MMC_HIGHSPEED;
		mmc->caps |= MMC_CAP_SD_HIGHSPEED;
		mmc->f_max = 24000000;
		dev_info(&udev->dev, "limiting SDIO speed to 24_MHz\n");
	} else {
		mmc->caps |= MMC_CAP_MMC_HIGHSPEED;
		mmc->caps |= MMC_CAP_SD_HIGHSPEED;
		mmc->f_max = 48000000;
	}
	mmc->f_min = 200000;
	mmc->max_blk_count = 511;
	mmc->max_blk_size = 512;
	mmc->max_segs = 128;
	if (force_max_req_size)
		mmc->max_req_size = force_max_req_size * 1024;
	else
		mmc->max_req_size = 64 * 1024;
	mmc->max_seg_size = mmc->max_req_size;
	mmc->ocr_avail = 0;
	mmc->ocr_avail |= MMC_VDD_165_195;
	mmc->ocr_avail |= MMC_VDD_20_21;
	mmc->ocr_avail |= MMC_VDD_21_22;
	mmc->ocr_avail |= MMC_VDD_22_23;
	mmc->ocr_avail |= MMC_VDD_23_24;
	mmc->ocr_avail |= MMC_VDD_24_25;
	mmc->ocr_avail |= MMC_VDD_25_26;
	mmc->ocr_avail |= MMC_VDD_26_27;
	mmc->ocr_avail |= MMC_VDD_27_28;
	mmc->ocr_avail |= MMC_VDD_28_29;
	mmc->ocr_avail |= MMC_VDD_29_30;
	mmc->ocr_avail |= MMC_VDD_30_31;
	mmc->ocr_avail |= MMC_VDD_31_32;
	mmc->ocr_avail |= MMC_VDD_32_33;
	mmc->ocr_avail |= MMC_VDD_33_34;
	mmc->ocr_avail |= MMC_VDD_34_35;
	mmc->ocr_avail |= MMC_VDD_35_36;
	mmc->ops = &vub300_mmc_ops;
	vub300 = mmc_priv(mmc);
	vub300->mmc = mmc;
	vub300->card_powered = 0;
	vub300->bus_width = 0;
	vub300->cmnd.head.block_size[0] = 0x00;
	vub300->cmnd.head.block_size[1] = 0x00;
	vub300->app_spec = 0;
	mutex_init(&vub300->cmd_mutex);
	mutex_init(&vub300->irq_mutex);
	vub300->command_out_urb = command_out_urb;
	vub300->command_res_urb = command_res_urb;
	vub300->usb_timed_out = 0;
	vub300->dynamic_register_count = 0;

	for (i = 0; i < ARRAY_SIZE(vub300->fn); i++) {
		vub300->fn[i].offload_point = 0;
		vub300->fn[i].offload_count = 0;
	}

	vub300->total_offload_count = 0;
	vub300->irq_enabled = 0;
	vub300->irq_disabled = 0;
	vub300->irqs_queued = 0;

	for (i = 0; i < ARRAY_SIZE(vub300->sdio_register); i++)
		vub300->sdio_register[i++].activate = 0;

	vub300->udev = udev;
	vub300->interface = interface;
	vub300->cmnd_res_ep = 0;
	vub300->cmnd_out_ep = 0;
	vub300->data_inp_ep = 0;
	vub300->data_out_ep = 0;

	for (i = 0; i < ARRAY_SIZE(vub300->fbs); i++)
		vub300->fbs[i] = 512;

	/*
	 *      set up the endpoint information
	 *
	 * use the first pair of bulk-in and bulk-out
	 *     endpoints for Command/Response+Interrupt
	 *
	 * use the second pair of bulk-in and bulk-out
	 *     endpoints for Data In/Out
	 */
	vub300->large_usb_packets = 0;
	iface_desc = interface->cur_altsetting;
	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
		struct usb_endpoint_descriptor *endpoint =
			&iface_desc->endpoint[i].desc;
		dev_info(&vub300->udev->dev,
			 "vub300 testing %s EndPoint(%d) %02X\n",
			 usb_endpoint_is_bulk_in(endpoint) ? "BULK IN" :
			 usb_endpoint_is_bulk_out(endpoint) ? "BULK OUT" :
			 "UNKNOWN", i, endpoint->bEndpointAddress);
		if (endpoint->wMaxPacketSize > 64)
			vub300->large_usb_packets = 1;
		if (usb_endpoint_is_bulk_in(endpoint)) {
			if (!vub300->cmnd_res_ep) {
				vub300->cmnd_res_ep =
					endpoint->bEndpointAddress;
			} else if (!vub300->data_inp_ep) {
				vub300->data_inp_ep =
					endpoint->bEndpointAddress;
			} else {
				dev_warn(&vub300->udev->dev,
					 "ignoring"
					 " unexpected bulk_in endpoint");
			}
		} else if (usb_endpoint_is_bulk_out(endpoint)) {
			if (!vub300->cmnd_out_ep) {
				vub300->cmnd_out_ep =
					endpoint->bEndpointAddress;
			} else if (!vub300->data_out_ep) {
				vub300->data_out_ep =
					endpoint->bEndpointAddress;
			} else {
				dev_warn(&vub300->udev->dev,
					 "ignoring"
					 " unexpected bulk_out endpoint");
			}
		} else {
			dev_warn(&vub300->udev->dev,
				 "vub300 ignoring EndPoint(%d) %02X", i,
				 endpoint->bEndpointAddress);
		}
	}
	if (vub300->cmnd_res_ep && vub300->cmnd_out_ep &&
	    vub300->data_inp_ep && vub300->data_out_ep) {
		dev_info(&vub300->udev->dev,
			 "vub300 %s packets"
			 " using EndPoints %02X %02X %02X %02X\n",
			 vub300->large_usb_packets ? "LARGE" : "SMALL",
			 vub300->cmnd_out_ep, vub300->cmnd_res_ep,
			 vub300->data_out_ep, vub300->data_inp_ep);
		/* we have the expected EndPoints */
	} else {
		dev_err(&vub300->udev->dev,
		    "Could not find two sets of bulk-in/out endpoint pairs\n");
		retval = -EINVAL;
		goto error5;
	}
	retval =
		usb_control_msg(vub300->udev, usb_rcvctrlpipe(vub300->udev, 0),
				GET_HC_INF0,
				USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
				0x0000, 0x0000, &vub300->hc_info,
				sizeof(vub300->hc_info), 1000);
	if (retval < 0)
		goto error5;
	retval =
		usb_control_msg(vub300->udev, usb_sndctrlpipe(vub300->udev, 0),
				SET_ROM_WAIT_STATES,
				USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
				firmware_rom_wait_states, 0x0000, NULL, 0, 1000);
	if (retval < 0)
		goto error5;
	dev_info(&vub300->udev->dev,
		 "operating_mode = %s %s %d MHz %s %d byte USB packets\n",
		 (mmc->caps & MMC_CAP_SDIO_IRQ) ? "IRQs" : "POLL",
		 (mmc->caps & MMC_CAP_4_BIT_DATA) ? "4-bit" : "1-bit",
		 mmc->f_max / 1000000,
		 pad_input_to_usb_pkt ? "padding input data to" : "with",
		 vub300->large_usb_packets ? 512 : 64);
	retval =
		usb_control_msg(vub300->udev, usb_rcvctrlpipe(vub300->udev, 0),
				GET_SYSTEM_PORT_STATUS,
				USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
				0x0000, 0x0000, &vub300->system_port_status,
				sizeof(vub300->system_port_status), 1000);
	if (retval < 0) {
		goto error4;
	} else if (sizeof(vub300->system_port_status) == retval) {
		vub300->card_present =
			(0x0001 & vub300->system_port_status.port_flags) ? 1 : 0;
		vub300->read_only =
			(0x0010 & vub300->system_port_status.port_flags) ? 1 : 0;
	} else {
		goto error4;
	}
	usb_set_intfdata(interface, vub300);
	INIT_DELAYED_WORK(&vub300->pollwork, vub300_pollwork_thread);
	INIT_WORK(&vub300->cmndwork, vub300_cmndwork_thread);
	INIT_WORK(&vub300->deadwork, vub300_deadwork_thread);
	kref_init(&vub300->kref);
	timer_setup(&vub300->sg_transfer_timer, vub300_sg_timed_out, 0);
	kref_get(&vub300->kref);
	timer_setup(&vub300->inactivity_timer,
		    vub300_inactivity_timer_expired, 0);
	vub300->inactivity_timer.expires = jiffies + HZ;
	add_timer(&vub300->inactivity_timer);
	if (vub300->card_present)
		dev_info(&vub300->udev->dev,
			 "USB vub300 remote SDIO host controller[%d]"
			 "connected with SD/SDIO card inserted\n",
			 interface_to_InterfaceNumber(interface));
	else
		dev_info(&vub300->udev->dev,
			 "USB vub300 remote SDIO host controller[%d]"
			 "connected with no SD/SDIO card inserted\n",
			 interface_to_InterfaceNumber(interface));
	mmc_add_host(mmc);
	return 0;
error5:
	mmc_free_host(mmc);
	/*
	 * and hence also frees vub300
	 * which is contained at the end of struct mmc
	 */
error4:
	usb_free_urb(command_res_urb);
error1:
	usb_free_urb(command_out_urb);
error0:
	usb_put_dev(udev);
	return retval;
}