struct usb_hcd { /* * housekeeping */ struct usb_bus self; /* hcd is-a bus */ struct kref kref; /* reference counter */ const char *product_desc; /* 主机控制器的产品描述字符串,对于UHCI,它为“UHCI Host Controller */ /*这里边儿保存的是“ehci-hcd:usb1”之类的字符串,也就是驱动的大名再加上总线编号。*/ char irq_descr[24]; struct timer_list rh_timer; /* drives root-hub polling */ struct urb *status_urb; /* the current status urb */ #ifdef CONFIG_PM struct work_struct wakeup_work; /* for remote wakeup */ #endif /* * hardware info/state */ const struct hc_driver *driver; /* hw-specific hooks */ /* Flags that need to be manipulated atomically */ unsigned long flags; #define HCD_FLAG_HW_ACCESSIBLE 0x00000001 #define HCD_FLAG_SAW_IRQ 0x00000002 unsigned rh_registered:1;/* is root hub registered? */ /* The next flag is a stopgap, to be removed when all the HCDs * support the new root-hub polling mechanism. */ unsigned uses_new_polling:1; unsigned poll_rh:1; /* poll for rh status? */ unsigned poll_pending:1; /* status has changed? */ unsigned wireless:1; /* Wireless USB HCD */ //wireless,是不是无线usb int irq; /* irq allocated */ void __iomem *regs; /* device memory/io */ u64 rsrc_start; /* memory/io resource start 是从表里读出来的host controller 的I/O 端口或内存的首地址*/ u64 rsrc_len; /* memory/io resource length 从表里读出来的host controller 的I/O 端口或内存的长度*/ unsigned power_budget; /* in mA, 0 = no limit 能够提供的电流*/ #define HCD_BUFFER_POOLS 4 //表示每个主机控制器可以有4 个dma 池 struct dma_pool *pool [HCD_BUFFER_POOLS]; int state; # define __ACTIVE 0x01 # define __SUSPEND 0x04 # define __TRANSIENT 0x80 # define HC_STATE_HALT 0 # define HC_STATE_RUNNING (__ACTIVE) # define HC_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE) # define HC_STATE_RESUMING (__SUSPEND|__TRANSIENT) # define HC_STATE_SUSPENDED (__SUSPEND) #define HC_IS_RUNNING(state) ((state) & __ACTIVE) #define HC_IS_SUSPENDED(state) ((state) & __SUSPEND) /* more shared queuing code would be good; it should support * smarter scheduling, handle transaction translators, etc; * input size of periodic table to an interrupt scheduler. * (ohci 32, uhci 1024, ehci 256/512/1024). */ /* The HC driver's private data is stored at the end of * this structure. */ unsigned long hcd_priv[0] __attribute__ ((aligned (sizeof(unsigned long)))); };
int hcd_buffer_create(struct usb_hcd *hcd) { char name[16]; int i, size; if (!hcd->self.controller->dma_mask) return 0; for (i = 0; i < HCD_BUFFER_POOLS; i++) { if (!(size = pool_max [i])) continue; snprintf(name, sizeof name, "buffer-%d", size); hcd->pool[i] = dma_pool_create(name, hcd->self.controller, size, size, 0); if (!hcd->pool [i]) { hcd_buffer_destroy(hcd); return -ENOMEM; } } return 0; }
首先要判断下这个主机控制器支持不支持DAM,如果支持DMA,就逐个适用dma_pool_alloc 来创建DMA 池,如果创建失败了,就调用同一个文件里的hcd_buffer_destroy 来将已经创建成功的池子给销毁掉。
void hcd_buffer_destroy(struct usb_hcd *hcd) { int i; for (i = 0; i < HCD_BUFFER_POOLS; i++) { struct dma_pool *pool = hcd->pool[i]; if (pool) { dma_pool_destroy(pool); hcd->pool[i] = NULL; } } }
一个用来取内存,一个用来释放内存。
void *hcd_buffer_alloc(struct usb_bus *bus,size_t size,gfp_t mem_flags,dma_addr_t *dma) { struct usb_hcd *hcd = bus_to_hcd(bus); int i; /* some USB hosts just use PIO */ if (!bus->controller->dma_mask) { *dma = ~(dma_addr_t) 0; return kmalloc(size, mem_flags); } for (i = 0; i < HCD_BUFFER_POOLS; i++) { if (size <= pool_max [i]) return dma_pool_alloc(hcd->pool [i], mem_flags, dma); } return dma_alloc_coherent(hcd->self.controller, size, dma, 0); } void hcd_buffer_free(struct usb_bus *bus,size_t size,void *addr,dma_addr_t dma) { struct usb_hcd *hcd = bus_to_hcd(bus); int i; if (!addr) return; if (!bus->controller->dma_mask) { kfree(addr); return; } for (i = 0; i < HCD_BUFFER_POOLS; i++) { if (size <= pool_max [i]) { dma_pool_free(hcd->pool [i], addr, dma); return; } } dma_free_coherent(hcd->self.controller, size, addr, dma); }