📄 ub.c
字号:
cmd->state = UB_CMDST_INIT; cmd->done = ub_probe_done; cmd->back = &compl; spin_lock_irqsave(&sc->lock, flags); cmd->tag = sc->tagcnt++; rc = ub_submit_scsi(sc, cmd); spin_unlock_irqrestore(&sc->lock, flags); if (rc != 0) { printk("ub: testing ready: submit error (%d)\n", rc); /* P3 */ goto err_submit; } wait_for_completion(&compl); rc = cmd->error;err_submit: kfree(cmd);err_alloc: return rc;}/* * Read the SCSI capacity synchronously (for probing). */static int ub_sync_read_cap(struct ub_dev *sc, struct ub_capacity *ret){ struct ub_scsi_cmd *cmd; char *p; enum { ALLOC_SIZE = sizeof(struct ub_scsi_cmd) + 8 }; unsigned long flags; unsigned int bsize, shift; unsigned long nsec; struct completion compl; int rc; init_completion(&compl); rc = -ENOMEM; if ((cmd = kmalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL) goto err_alloc; memset(cmd, 0, ALLOC_SIZE); p = (char *)cmd + sizeof(struct ub_scsi_cmd); cmd->cdb[0] = 0x25; cmd->cdb_len = 10; cmd->dir = UB_DIR_READ; cmd->state = UB_CMDST_INIT; cmd->data = p; cmd->len = 8; cmd->done = ub_probe_done; cmd->back = &compl; spin_lock_irqsave(&sc->lock, flags); cmd->tag = sc->tagcnt++; rc = ub_submit_scsi(sc, cmd); spin_unlock_irqrestore(&sc->lock, flags); if (rc != 0) { printk("ub: reading capacity: submit error (%d)\n", rc); /* P3 */ goto err_submit; } wait_for_completion(&compl); if (cmd->error != 0) { printk("ub: reading capacity: error %d\n", cmd->error); /* P3 */ rc = -EIO; goto err_read; } if (cmd->act_len != 8) { printk("ub: reading capacity: size %d\n", cmd->act_len); /* P3 */ rc = -EIO; goto err_read; } /* sd.c special-cases sector size of 0 to mean 512. Needed? Safe? */ nsec = be32_to_cpu(*(u32 *)p) + 1; bsize = be32_to_cpu(*(u32 *)(p + 4)); switch (bsize) { case 512: shift = 0; break; case 1024: shift = 1; break; case 2048: shift = 2; break; case 4096: shift = 3; break; default: printk("ub: Bad sector size %u\n", bsize); /* P3 */ rc = -EDOM; goto err_inv_bsize; } ret->bsize = bsize; ret->bshift = shift; ret->nsec = nsec << shift; rc = 0;err_inv_bsize:err_read:err_submit: kfree(cmd);err_alloc: return rc;}/* */static void ub_probe_urb_complete(struct urb *urb, struct pt_regs *pt){ struct completion *cop = urb->context; complete(cop);}static void ub_probe_timeout(unsigned long arg){ struct completion *cop = (struct completion *) arg; complete(cop);}/* * Clear initial stalls. */static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe){ int endp; struct usb_ctrlrequest *cr; struct completion compl; struct timer_list timer; int rc; init_completion(&compl); endp = usb_pipeendpoint(stalled_pipe); if (usb_pipein (stalled_pipe)) endp |= USB_DIR_IN; cr = &sc->work_cr; cr->bRequestType = USB_RECIP_ENDPOINT; cr->bRequest = USB_REQ_CLEAR_FEATURE; cr->wValue = cpu_to_le16(USB_ENDPOINT_HALT); cr->wIndex = cpu_to_le16(endp); cr->wLength = cpu_to_le16(0); usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe, (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl); sc->work_urb.transfer_flags = 0; sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; init_timer(&timer); timer.function = ub_probe_timeout; timer.data = (unsigned long) &compl; timer.expires = jiffies + UB_CTRL_TIMEOUT; add_timer(&timer); if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) { printk(KERN_WARNING "%s: Unable to submit a probe clear (%d)\n", sc->name, rc); del_timer_sync(&timer); return rc; } wait_for_completion(&compl); del_timer_sync(&timer); /* * Most of the time, URB was done and dev set to NULL, and so * the unlink bounces out with ENODEV. We do not call usb_kill_urb * because we still think about a backport to 2.4. */ usb_unlink_urb(&sc->work_urb); /* reset the endpoint toggle */ usb_settoggle(sc->dev, endp, usb_pipeout(sc->last_pipe), 0); return 0;}/* * Get the pipe settings. */static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev, struct usb_interface *intf){ struct usb_host_interface *altsetting = intf->cur_altsetting; struct usb_endpoint_descriptor *ep_in = NULL; struct usb_endpoint_descriptor *ep_out = NULL; struct usb_endpoint_descriptor *ep; int i; /* * Find the endpoints we need. * We are expecting a minimum of 2 endpoints - in and out (bulk). * We will ignore any others. */ for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { ep = &altsetting->endpoint[i].desc; /* Is it a BULK endpoint? */ if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { /* BULK in or out? */ if (ep->bEndpointAddress & USB_DIR_IN) ep_in = ep; else ep_out = ep; } } if (ep_in == NULL || ep_out == NULL) { printk(KERN_NOTICE "%s: device %u failed endpoint check\n", sc->name, sc->dev->devnum); return -EIO; } /* Calculate and store the pipe values */ sc->send_ctrl_pipe = usb_sndctrlpipe(dev, 0); sc->recv_ctrl_pipe = usb_rcvctrlpipe(dev, 0); sc->send_bulk_pipe = usb_sndbulkpipe(dev, ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); sc->recv_bulk_pipe = usb_rcvbulkpipe(dev, ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); return 0;}/* * Probing is done in the process context, which allows us to cheat * and not to build a state machine for the discovery. */static int ub_probe(struct usb_interface *intf, const struct usb_device_id *dev_id){ struct ub_dev *sc; request_queue_t *q; struct gendisk *disk; int rc; rc = -ENOMEM; if ((sc = kmalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL) goto err_core; memset(sc, 0, sizeof(struct ub_dev)); spin_lock_init(&sc->lock); usb_init_urb(&sc->work_urb); tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc); atomic_set(&sc->poison, 0); init_timer(&sc->work_timer); sc->work_timer.data = (unsigned long) sc; sc->work_timer.function = ub_urb_timeout; ub_init_completion(&sc->work_done); sc->work_done.done = 1; /* A little yuk, but oh well... */ rc = -ENOSR; if ((sc->id = ub_id_get()) == -1) goto err_id; snprintf(sc->name, 8, DRV_NAME "%c", sc->id + 'a'); sc->dev = interface_to_usbdev(intf); sc->intf = intf; // sc->ifnum = intf->cur_altsetting->desc.bInterfaceNumber; usb_set_intfdata(intf, sc); usb_get_dev(sc->dev); // usb_get_intf(sc->intf); /* Do we need this? */ /* XXX Verify that we can handle the device (from descriptors) */ ub_get_pipes(sc, sc->dev, intf); if (device_create_file(&sc->intf->dev, &dev_attr_diag) != 0) goto err_diag; /* * At this point, all USB initialization is done, do upper layer. * We really hate halfway initialized structures, so from the * invariants perspective, this ub_dev is fully constructed at * this point. */ /* * This is needed to clear toggles. It is a problem only if we do * `rmmod ub && modprobe ub` without disconnects, but we like that. */ ub_probe_clear_stall(sc, sc->recv_bulk_pipe); ub_probe_clear_stall(sc, sc->send_bulk_pipe); /* * The way this is used by the startup code is a little specific. * A SCSI check causes a USB stall. Our common case code sees it * and clears the check, after which the device is ready for use. * But if a check was not present, any command other than * TEST_UNIT_READY ends with a lockup (including REQUEST_SENSE). * * If we neglect to clear the SCSI check, the first real command fails * (which is the capacity readout). We clear that and retry, but why * causing spurious retries for no reason. * * Revalidation may start with its own TEST_UNIT_READY, but that one * has to succeed, so we clear checks with an additional one here. * In any case it's not our business how revaliadation is implemented. */ ub_sync_tur(sc); sc->removable = 1; /* XXX Query this from the device */ ub_revalidate(sc); /* This is pretty much a long term P3 */ printk(KERN_INFO "%s: device %u capacity nsec %ld bsize %u\n", sc->name, sc->dev->devnum, sc->capacity.nsec, sc->capacity.bsize); /* * Just one disk per sc currently, but maybe more. */ rc = -ENOMEM; if ((disk = alloc_disk(UB_MINORS_PER_MAJOR)) == NULL) goto err_diskalloc; sc->disk = disk; sprintf(disk->disk_name, DRV_NAME "%c", sc->id + 'a'); sprintf(disk->devfs_name, DEVFS_NAME "/%c", sc->id + 'a'); disk->major = UB_MAJOR; disk->first_minor = sc->id * UB_MINORS_PER_MAJOR; disk->fops = &ub_bd_fops; disk->private_data = sc; disk->driverfs_dev = &intf->dev; rc = -ENOMEM; if ((q = blk_init_queue(ub_bd_rq_fn, &sc->lock)) == NULL) goto err_blkqinit; disk->queue = q; // blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask); blk_queue_max_hw_segments(q, UB_MAX_REQ_SG); blk_queue_max_phys_segments(q, UB_MAX_REQ_SG); // blk_queue_segment_boundary(q, CARM_SG_BOUNDARY); blk_queue_max_sectors(q, UB_MAX_SECTORS); // blk_queue_hardsect_size(q, xxxxx); /* * This is a serious infraction, caused by a deficiency in the * USB sg interface (usb_sg_wait()). We plan to remove this once * we get mileage on the driver and can justify a change to USB API. * See blk_queue_bounce_limit() to understand this part. * * XXX And I still need to be aware of the DMA mask in the HC. */ q->bounce_pfn = blk_max_low_pfn; q->bounce_gfp = GFP_NOIO; q->queuedata = sc; set_capacity(disk, sc->capacity.nsec); if (sc->removable) disk->flags |= GENHD_FL_REMOVABLE; add_disk(disk); return 0;err_blkqinit: put_disk(disk);err_diskalloc: device_remove_file(&sc->intf->dev, &dev_attr_diag);err_diag: usb_set_intfdata(intf, NULL); // usb_put_intf(sc->intf); usb_put_dev(sc->dev); spin_lock_irq(&ub_lock); ub_id_put(sc->id); spin_unlock_irq(&ub_lock);err_id: kfree(sc);err_core: return rc;}static void ub_disconnect(struct usb_interface *intf){ struct ub_dev *sc = usb_get_intfdata(intf); struct gendisk *disk = sc->disk; request_queue_t *q = disk->queue; unsigned long flags; /* * Fence stall clearnings, operations triggered by unlinkings and so on. * We do not attempt to unlink any URBs, because we do not trust the * unlink paths in HC drivers. Also, we get -84 upon disconnect anyway. */ atomic_set(&sc->poison, 1); /* * Blow away queued commands. * * Actually, this never works, because before we get here * the HCD terminates outstanding URB(s). It causes our * SCSI command queue to advance, commands fail to submit, * and the whole queue drains. So, we just use this code to * print warnings. */ spin_lock_irqsave(&sc->lock, flags); { struct ub_scsi_cmd *cmd; int cnt = 0; while ((cmd = ub_cmdq_pop(sc)) != NULL) { cmd->error = -ENOTCONN; cmd->state = UB_CMDST_DONE; ub_cmdtr_state(sc, cmd); ub_cmdq_pop(sc); (*cmd->done)(sc, cmd); cnt++; } if (cnt != 0) { printk(KERN_WARNING "%s: " "%d was queued after shutdown\n", sc->name, cnt); } } spin_unlock_irqrestore(&sc->lock, flags); /* * Unregister the upper layer, this waits for all commands to end. */ if (disk->flags & GENHD_FL_UP) del_gendisk(disk); if (q) blk_cleanup_queue(q); /* * If we zero disk->private_data BEFORE put_disk, we have to check * for NULL all over the place in open, release, check_media and * revalidate, because the block level semaphore is well inside the * put_disk. But we cannot zero after the call, because *disk is gone. * The sd.c is blatantly racy in this area. */ /* disk->private_data = NULL; */ put_disk(disk); sc->disk = NULL; /* * We really expect blk_cleanup_queue() to wait, so no amount * of paranoya is too much. * * Taking a lock on a structure which is about to be freed * is very nonsensual. Here it is largely a way to do a debug freeze, * and a bracket which shows where the nonsensual code segment ends. * * Testing for -EINPROGRESS is always a bug, so we are bending * the rules a little. */ spin_lock_irqsave(&sc->lock, flags); if (sc->work_urb.status == -EINPROGRESS) { /* janitors: ignore */ printk(KERN_WARNING "%s: " "URB is active after disconnect\n", sc->name); } spin_unlock_irqrestore(&sc->lock, flags); /* * At this point there must be no commands coming from anyone * and no URBs left in transit. */ device_remove_file(&sc->intf->dev, &dev_attr_diag); usb_set_intfdata(intf, NULL); // usb_put_intf(sc->intf); sc->intf = NULL; usb_put_dev(sc->dev); sc->dev = NULL; spin_lock_irqsave(&ub_lock, flags); if (sc->openc == 0) ub_cleanup(sc); spin_unlock_irqrestore(&ub_lock, flags);}struct usb_driver ub_driver = { .owner = THIS_MODULE, .name = "ub", .probe = ub_probe, .disconnect = ub_disconnect, .id_table = ub_usb_ids,};static int __init ub_init(void){ int rc; /* P3 */ printk("ub: sizeof ub_scsi_cmd %zu ub_dev %zu\n", sizeof(struct ub_scsi_cmd), sizeof(struct ub_dev)); if ((rc = register_blkdev(UB_MAJOR, DRV_NAME)) != 0) goto err_regblkdev; devfs_mk_dir(DEVFS_NAME); if ((rc = usb_register(&ub_driver)) != 0) goto err_register; return 0;err_register: devfs_remove(DEVFS_NAME); unregister_blkdev(UB_MAJOR, DRV_NAME);err_regblkdev: return rc;}static void __exit ub_exit(void){ usb_deregister(&ub_driver); devfs_remove(DEVFS_NAME); unregister_blkdev(UB_MAJOR, DRV_NAME);}module_init(ub_init);module_exit(ub_exit);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -