Commit 5326862d authored by Linus Torvalds's avatar Linus Torvalds

Automerge

parents a2f1b7bc cfc632c8
...@@ -28,7 +28,7 @@ struct aligninfo { ...@@ -28,7 +28,7 @@ struct aligninfo {
#define OPCD(inst) (((inst) & 0xFC000000) >> 26) #define OPCD(inst) (((inst) & 0xFC000000) >> 26)
#define RS(inst) (((inst) & 0x03E00000) >> 21) #define RS(inst) (((inst) & 0x03E00000) >> 21)
#define RA(inst) (((inst) & 0x001F0000) >> 16) #define RA(inst) (((inst) & 0x001F0000) >> 16)
#define IS_DFORM(code) ((code) >= 32 && (code) <= 47) #define IS_DFORM(code) ((code) >= 32 && (code) <= 55)
#endif #endif
#define INVALID { 0, 0 } #define INVALID { 0, 0 }
......
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
#define FB_MAX 8 #define FB_MAX 8
#endif #endif
#define ALIGN(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long)) #define ALIGNUL(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))
struct prom_args { struct prom_args {
const char *service; const char *service;
...@@ -376,7 +376,7 @@ check_display(unsigned long mem) ...@@ -376,7 +376,7 @@ check_display(unsigned long mem)
} }
} }
return ALIGN(mem); return ALIGNUL(mem);
} }
/* This function will enable the early boot text when doing OF booting. This /* This function will enable the early boot text when doing OF booting. This
...@@ -457,7 +457,7 @@ copy_device_tree(unsigned long mem_start, unsigned long mem_end) ...@@ -457,7 +457,7 @@ copy_device_tree(unsigned long mem_start, unsigned long mem_end)
prom_exit(); prom_exit();
} }
allnextp = &allnodes; allnextp = &allnodes;
mem_start = ALIGN(mem_start); mem_start = ALIGNUL(mem_start);
new_start = inspect_node(root, 0, mem_start, mem_end, &allnextp); new_start = inspect_node(root, 0, mem_start, mem_end, &allnextp);
*allnextp = 0; *allnextp = 0;
return new_start; return new_start;
...@@ -501,7 +501,7 @@ inspect_node(phandle node, struct device_node *dad, ...@@ -501,7 +501,7 @@ inspect_node(phandle node, struct device_node *dad,
if ((int) call_prom("nextprop", 3, 1, node, prev_name, if ((int) call_prom("nextprop", 3, 1, node, prev_name,
namep) <= 0) namep) <= 0)
break; break;
mem_start = ALIGN((unsigned long)namep + strlen(namep) + 1); mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1);
prev_name = namep; prev_name = namep;
valp = (unsigned char *) mem_start; valp = (unsigned char *) mem_start;
pp->value = PTRUNRELOC(valp); pp->value = PTRUNRELOC(valp);
...@@ -514,7 +514,7 @@ inspect_node(phandle node, struct device_node *dad, ...@@ -514,7 +514,7 @@ inspect_node(phandle node, struct device_node *dad,
if (pp->length > MAX_PROPERTY_LENGTH) if (pp->length > MAX_PROPERTY_LENGTH)
continue; /* ignore this property */ continue; /* ignore this property */
#endif #endif
mem_start = ALIGN(mem_start + pp->length); mem_start = ALIGNUL(mem_start + pp->length);
*prev_propp = PTRUNRELOC(pp); *prev_propp = PTRUNRELOC(pp);
prev_propp = &pp->next; prev_propp = &pp->next;
} }
...@@ -526,7 +526,7 @@ inspect_node(phandle node, struct device_node *dad, ...@@ -526,7 +526,7 @@ inspect_node(phandle node, struct device_node *dad,
namep = (char *) (pp + 1); namep = (char *) (pp + 1);
pp->name = PTRUNRELOC(namep); pp->name = PTRUNRELOC(namep);
strcpy(namep, "linux,phandle"); strcpy(namep, "linux,phandle");
mem_start = ALIGN((unsigned long)namep + strlen(namep) + 1); mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1);
pp->value = (unsigned char *) PTRUNRELOC(&np->node); pp->value = (unsigned char *) PTRUNRELOC(&np->node);
pp->length = sizeof(np->node); pp->length = sizeof(np->node);
} }
...@@ -538,7 +538,7 @@ inspect_node(phandle node, struct device_node *dad, ...@@ -538,7 +538,7 @@ inspect_node(phandle node, struct device_node *dad,
if (l >= 0) { if (l >= 0) {
np->full_name = PTRUNRELOC((char *) mem_start); np->full_name = PTRUNRELOC((char *) mem_start);
*(char *)(mem_start + l) = 0; *(char *)(mem_start + l) = 0;
mem_start = ALIGN(mem_start + l + 1); mem_start = ALIGNUL(mem_start + l + 1);
} }
/* do all our children */ /* do all our children */
...@@ -741,7 +741,7 @@ prom_init(int r3, int r4, prom_entry pp) ...@@ -741,7 +741,7 @@ prom_init(int r3, int r4, prom_entry pp)
*d = 0; *d = 0;
call_prom("canon", 3, 1, p, d, 1<<20); call_prom("canon", 3, 1, p, d, 1<<20);
bootdevice = PTRUNRELOC(d); bootdevice = PTRUNRELOC(d);
mem = ALIGN(mem + strlen(d) + 1); mem = ALIGNUL(mem + strlen(d) + 1);
} }
prom_instantiate_rtas(); prom_instantiate_rtas();
......
...@@ -400,13 +400,17 @@ heathrow_modem_enable(struct device_node* node, int param, int value) ...@@ -400,13 +400,17 @@ heathrow_modem_enable(struct device_node* node, int param, int value)
LOCK(flags); LOCK(flags);
MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1); MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);
(void)MACIO_IN8(HRW_GPIO_MODEM_RESET); (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
UNLOCK(flags); mdelay(250); LOCK(flags); UNLOCK(flags);
mdelay(250);
LOCK(flags);
MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio); MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio);
(void)MACIO_IN8(HRW_GPIO_MODEM_RESET); (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
UNLOCK(flags); mdelay(250); LOCK(flags); UNLOCK(flags);
mdelay(250);
LOCK(flags);
MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1); MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);
(void)MACIO_IN8(HRW_GPIO_MODEM_RESET); (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
UNLOCK(flags); mdelay(250); LOCK(flags); UNLOCK(flags);
} }
return 0; return 0;
} }
......
...@@ -1710,7 +1710,6 @@ struct pci_pool { /* the pool */ ...@@ -1710,7 +1710,6 @@ struct pci_pool { /* the pool */
spinlock_t lock; spinlock_t lock;
size_t blocks_per_page; size_t blocks_per_page;
size_t size; size_t size;
int flags;
struct pci_dev *dev; struct pci_dev *dev;
size_t allocation; size_t allocation;
char name [32]; char name [32];
...@@ -1727,8 +1726,6 @@ struct pci_page { /* cacheable header for 'allocation' bytes */ ...@@ -1727,8 +1726,6 @@ struct pci_page { /* cacheable header for 'allocation' bytes */
#define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000) #define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000)
#define POOL_POISON_BYTE 0xa7 #define POOL_POISON_BYTE 0xa7
// #define CONFIG_PCIPOOL_DEBUG
/** /**
* pci_pool_create - Creates a pool of pci consistent memory blocks, for dma. * pci_pool_create - Creates a pool of pci consistent memory blocks, for dma.
...@@ -1737,7 +1734,7 @@ struct pci_page { /* cacheable header for 'allocation' bytes */ ...@@ -1737,7 +1734,7 @@ struct pci_page { /* cacheable header for 'allocation' bytes */
* @size: size of the blocks in this pool. * @size: size of the blocks in this pool.
* @align: alignment requirement for blocks; must be a power of two * @align: alignment requirement for blocks; must be a power of two
* @allocation: returned blocks won't cross this boundary (or zero) * @allocation: returned blocks won't cross this boundary (or zero)
* @flags: SLAB_* flags (not all are supported). * @mem_flags: SLAB_* flags.
* *
* Returns a pci allocation pool with the requested characteristics, or * Returns a pci allocation pool with the requested characteristics, or
* null if one can't be created. Given one of these pools, pci_pool_alloc() * null if one can't be created. Given one of these pools, pci_pool_alloc()
...@@ -1753,7 +1750,7 @@ struct pci_page { /* cacheable header for 'allocation' bytes */ ...@@ -1753,7 +1750,7 @@ struct pci_page { /* cacheable header for 'allocation' bytes */
*/ */
struct pci_pool * struct pci_pool *
pci_pool_create (const char *name, struct pci_dev *pdev, pci_pool_create (const char *name, struct pci_dev *pdev,
size_t size, size_t align, size_t allocation, int flags) size_t size, size_t align, size_t allocation, int mem_flags)
{ {
struct pci_pool *retval; struct pci_pool *retval;
...@@ -1777,13 +1774,9 @@ pci_pool_create (const char *name, struct pci_dev *pdev, ...@@ -1777,13 +1774,9 @@ pci_pool_create (const char *name, struct pci_dev *pdev,
} else if (allocation < size) } else if (allocation < size)
return 0; return 0;
if (!(retval = kmalloc (sizeof *retval, flags))) if (!(retval = kmalloc (sizeof *retval, mem_flags)))
return retval; return retval;
#ifdef CONFIG_PCIPOOL_DEBUG
flags |= SLAB_POISON;
#endif
strncpy (retval->name, name, sizeof retval->name); strncpy (retval->name, name, sizeof retval->name);
retval->name [sizeof retval->name - 1] = 0; retval->name [sizeof retval->name - 1] = 0;
...@@ -1791,17 +1784,10 @@ pci_pool_create (const char *name, struct pci_dev *pdev, ...@@ -1791,17 +1784,10 @@ pci_pool_create (const char *name, struct pci_dev *pdev,
INIT_LIST_HEAD (&retval->page_list); INIT_LIST_HEAD (&retval->page_list);
spin_lock_init (&retval->lock); spin_lock_init (&retval->lock);
retval->size = size; retval->size = size;
retval->flags = flags;
retval->allocation = allocation; retval->allocation = allocation;
retval->blocks_per_page = allocation / size; retval->blocks_per_page = allocation / size;
init_waitqueue_head (&retval->waitq); init_waitqueue_head (&retval->waitq);
#ifdef CONFIG_PCIPOOL_DEBUG
printk (KERN_DEBUG "pcipool create %s/%s size %d, %d/page (%d alloc)\n",
pdev ? pdev->slot_name : NULL, retval->name, size,
retval->blocks_per_page, allocation);
#endif
return retval; return retval;
} }
...@@ -1824,8 +1810,9 @@ pool_alloc_page (struct pci_pool *pool, int mem_flags) ...@@ -1824,8 +1810,9 @@ pool_alloc_page (struct pci_pool *pool, int mem_flags)
&page->dma); &page->dma);
if (page->vaddr) { if (page->vaddr) {
memset (page->bitmap, 0xff, mapsize); // bit set == free memset (page->bitmap, 0xff, mapsize); // bit set == free
if (pool->flags & SLAB_POISON) #ifdef CONFIG_DEBUG_SLAB
memset (page->vaddr, POOL_POISON_BYTE, pool->allocation); memset (page->vaddr, POOL_POISON_BYTE, pool->allocation);
#endif
list_add (&page->page_list, &pool->page_list); list_add (&page->page_list, &pool->page_list);
} else { } else {
kfree (page); kfree (page);
...@@ -1851,8 +1838,9 @@ pool_free_page (struct pci_pool *pool, struct pci_page *page) ...@@ -1851,8 +1838,9 @@ pool_free_page (struct pci_pool *pool, struct pci_page *page)
{ {
dma_addr_t dma = page->dma; dma_addr_t dma = page->dma;
if (pool->flags & SLAB_POISON) #ifdef CONFIG_DEBUG_SLAB
memset (page->vaddr, POOL_POISON_BYTE, pool->allocation); memset (page->vaddr, POOL_POISON_BYTE, pool->allocation);
#endif
pci_free_consistent (pool->dev, pool->allocation, page->vaddr, dma); pci_free_consistent (pool->dev, pool->allocation, page->vaddr, dma);
list_del (&page->page_list); list_del (&page->page_list);
kfree (page); kfree (page);
...@@ -1871,12 +1859,6 @@ pci_pool_destroy (struct pci_pool *pool) ...@@ -1871,12 +1859,6 @@ pci_pool_destroy (struct pci_pool *pool)
{ {
unsigned long flags; unsigned long flags;
#ifdef CONFIG_PCIPOOL_DEBUG
printk (KERN_DEBUG "pcipool destroy %s/%s\n",
pool->dev ? pool->dev->slot_name : NULL,
pool->name);
#endif
spin_lock_irqsave (&pool->lock, flags); spin_lock_irqsave (&pool->lock, flags);
while (!list_empty (&pool->page_list)) { while (!list_empty (&pool->page_list)) {
struct pci_page *page; struct pci_page *page;
...@@ -2010,30 +1992,27 @@ pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t dma) ...@@ -2010,30 +1992,27 @@ pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t dma)
pool->name, vaddr, (unsigned long) dma); pool->name, vaddr, (unsigned long) dma);
return; return;
} }
#ifdef CONFIG_PCIPOOL_DEBUG
if (((dma - page->dma) + (void *)page->vaddr) != vaddr) {
printk (KERN_ERR "pci_pool_free %s/%s, %p (bad vaddr)/%lx\n",
pool->dev ? pool->dev->slot_name : NULL,
pool->name, vaddr, (unsigned long) dma);
return;
}
#endif
block = dma - page->dma; block = dma - page->dma;
block /= pool->size; block /= pool->size;
map = block / BITS_PER_LONG; map = block / BITS_PER_LONG;
block %= BITS_PER_LONG; block %= BITS_PER_LONG;
#ifdef CONFIG_PCIPOOL_DEBUG #ifdef CONFIG_DEBUG_SLAB
if (((dma - page->dma) + (void *)page->vaddr) != vaddr) {
printk (KERN_ERR "pci_pool_free %s/%s, %p (bad vaddr)/%lx\n",
pool->dev ? pool->dev->slot_name : NULL,
pool->name, vaddr, (unsigned long) dma);
return;
}
if (page->bitmap [map] & (1UL << block)) { if (page->bitmap [map] & (1UL << block)) {
printk (KERN_ERR "pci_pool_free %s/%s, dma %x already free\n", printk (KERN_ERR "pci_pool_free %s/%s, dma %x already free\n",
pool->dev ? pool->dev->slot_name : NULL, pool->dev ? pool->dev->slot_name : NULL,
pool->name, dma); pool->name, dma);
return; return;
} }
#endif
if (pool->flags & SLAB_POISON)
memset (vaddr, POOL_POISON_BYTE, pool->size); memset (vaddr, POOL_POISON_BYTE, pool->size);
#endif
spin_lock_irqsave (&pool->lock, flags); spin_lock_irqsave (&pool->lock, flags);
set_bit (block, &page->bitmap [map]); set_bit (block, &page->bitmap [map]);
......
...@@ -382,6 +382,7 @@ CONFIG_USB_KAWETH ...@@ -382,6 +382,7 @@ CONFIG_USB_KAWETH
CONFIG_USB_CATC CONFIG_USB_CATC
Say Y if you want to use one of the following 10Mbps USB Ethernet Say Y if you want to use one of the following 10Mbps USB Ethernet
device based on the EL1210A chip. Supported devices are: device based on the EL1210A chip. Supported devices are:
Belkin F5U011
Belkin F5U111 Belkin F5U111
CATC NetMate CATC NetMate
CATC NetMate II CATC NetMate II
......
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
* *
* Based on the work of * Based on the work of
* Donald Becker * Donald Becker
*
* Old chipset support added by Simon Evans <spse@secret.org.uk> 2002
* - adds support for Belkin F5U011
*/ */
/* /*
...@@ -70,6 +73,7 @@ MODULE_LICENSE("GPL"); ...@@ -70,6 +73,7 @@ MODULE_LICENSE("GPL");
#define RX_MAX_BURST 15 /* Max packets per rx buffer (> 0, < 16) */ #define RX_MAX_BURST 15 /* Max packets per rx buffer (> 0, < 16) */
#define TX_MAX_BURST 15 /* Max full sized packets per tx buffer (> 0) */ #define TX_MAX_BURST 15 /* Max full sized packets per tx buffer (> 0) */
#define CTRL_QUEUE 16 /* Max control requests in flight (power of two) */ #define CTRL_QUEUE 16 /* Max control requests in flight (power of two) */
#define RX_PKT_SZ 1600 /* Max size of receive packet for F5U011 */
/* /*
* Control requests. * Control requests.
...@@ -80,6 +84,7 @@ enum control_requests { ...@@ -80,6 +84,7 @@ enum control_requests {
GetMac = 0xf2, GetMac = 0xf2,
Reset = 0xf4, Reset = 0xf4,
SetMac = 0xf5, SetMac = 0xf5,
SetRxMode = 0xf5, /* F5U011 only */
WriteROM = 0xf8, WriteROM = 0xf8,
SetReg = 0xfa, SetReg = 0xfa,
GetReg = 0xfb, GetReg = 0xfb,
...@@ -127,6 +132,7 @@ enum rx_filter_bits { ...@@ -127,6 +132,7 @@ enum rx_filter_bits {
RxForceOK = 0x04, RxForceOK = 0x04,
RxMultiCast = 0x08, RxMultiCast = 0x08,
RxPromisc = 0x10, RxPromisc = 0x10,
AltRxPromisc = 0x20, /* F5U011 uses different bit */
}; };
enum led_values { enum led_values {
...@@ -137,6 +143,12 @@ enum led_values { ...@@ -137,6 +143,12 @@ enum led_values {
LEDLink = 0x08, LEDLink = 0x08,
}; };
enum link_status {
LinkNoChange = 0,
LinkGood = 1,
LinkBad = 2
};
/* /*
* The catc struct. * The catc struct.
*/ */
...@@ -180,6 +192,10 @@ struct catc { ...@@ -180,6 +192,10 @@ struct catc {
} ctrl_queue[CTRL_QUEUE]; } ctrl_queue[CTRL_QUEUE];
struct urb *tx_urb, *rx_urb, *irq_urb, *ctrl_urb; struct urb *tx_urb, *rx_urb, *irq_urb, *ctrl_urb;
u8 is_f5u011; /* Set if device is an F5U011 */
u8 rxmode[2]; /* Used for F5U011 */
atomic_t recq_sz; /* Used for F5U011 - counter of waiting rx packets */
}; };
/* /*
...@@ -193,6 +209,10 @@ struct catc { ...@@ -193,6 +209,10 @@ struct catc {
#define catc_write_mem(catc, addr, buf, size) catc_ctrl_msg(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size) #define catc_write_mem(catc, addr, buf, size) catc_ctrl_msg(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size)
#define catc_read_mem(catc, addr, buf, size) catc_ctrl_msg(catc, USB_DIR_IN, ReadMem, 0, addr, buf, size) #define catc_read_mem(catc, addr, buf, size) catc_ctrl_msg(catc, USB_DIR_IN, ReadMem, 0, addr, buf, size)
#define f5u011_rxmode(catc, rxmode) catc_ctrl_msg(catc, USB_DIR_OUT, SetRxMode, 0, 1, rxmode, 2)
#define f5u011_rxmode_async(catc, rxmode) catc_ctrl_async(catc, USB_DIR_OUT, SetRxMode, 0, 1, &rxmode, 2, NULL)
#define f5u011_mchash_async(catc, hash) catc_ctrl_async(catc, USB_DIR_OUT, SetRxMode, 0, 2, &hash, 8, NULL)
#define catc_set_reg_async(catc, reg, val) catc_ctrl_async(catc, USB_DIR_OUT, SetReg, val, reg, NULL, 0, NULL) #define catc_set_reg_async(catc, reg, val) catc_ctrl_async(catc, USB_DIR_OUT, SetReg, val, reg, NULL, 0, NULL)
#define catc_get_reg_async(catc, reg, cb) catc_ctrl_async(catc, USB_DIR_IN, GetReg, 0, reg, NULL, 1, cb) #define catc_get_reg_async(catc, reg, cb) catc_ctrl_async(catc, USB_DIR_IN, GetReg, 0, reg, NULL, 1, cb)
#define catc_write_mem_async(catc, addr, buf, size) catc_ctrl_async(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size, NULL) #define catc_write_mem_async(catc, addr, buf, size) catc_ctrl_async(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size, NULL)
...@@ -206,9 +226,12 @@ static void catc_rx_done(struct urb *urb) ...@@ -206,9 +226,12 @@ static void catc_rx_done(struct urb *urb)
struct catc *catc = urb->context; struct catc *catc = urb->context;
u8 *pkt_start = urb->transfer_buffer; u8 *pkt_start = urb->transfer_buffer;
struct sk_buff *skb; struct sk_buff *skb;
int pkt_len; int pkt_len, pkt_offset = 0;
if (!catc->is_f5u011) {
clear_bit(RX_RUNNING, &catc->flags); clear_bit(RX_RUNNING, &catc->flags);
pkt_offset = 2;
}
if (urb->status) { if (urb->status) {
dbg("rx_done, status %d, length %d", urb->status, urb->actual_length); dbg("rx_done, status %d, length %d", urb->status, urb->actual_length);
...@@ -216,19 +239,22 @@ static void catc_rx_done(struct urb *urb) ...@@ -216,19 +239,22 @@ static void catc_rx_done(struct urb *urb)
} }
do { do {
if(!catc->is_f5u011) {
pkt_len = le16_to_cpup((u16*)pkt_start); pkt_len = le16_to_cpup((u16*)pkt_start);
if (pkt_len > urb->actual_length) { if (pkt_len > urb->actual_length) {
catc->stats.rx_length_errors++; catc->stats.rx_length_errors++;
catc->stats.rx_errors++; catc->stats.rx_errors++;
break; break;
} }
} else {
pkt_len = urb->actual_length;
}
if (!(skb = dev_alloc_skb(pkt_len))) if (!(skb = dev_alloc_skb(pkt_len)))
return; return;
skb->dev = catc->netdev; skb->dev = catc->netdev;
eth_copy_and_sum(skb, pkt_start + 2, pkt_len, 0); eth_copy_and_sum(skb, pkt_start + pkt_offset, pkt_len, 0);
skb_put(skb, pkt_len); skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, catc->netdev); skb->protocol = eth_type_trans(skb, catc->netdev);
...@@ -237,11 +263,28 @@ static void catc_rx_done(struct urb *urb) ...@@ -237,11 +263,28 @@ static void catc_rx_done(struct urb *urb)
catc->stats.rx_packets++; catc->stats.rx_packets++;
catc->stats.rx_bytes += pkt_len; catc->stats.rx_bytes += pkt_len;
/* F5U011 only does one packet per RX */
if (catc->is_f5u011)
break;
pkt_start += (((pkt_len + 1) >> 6) + 1) << 6; pkt_start += (((pkt_len + 1) >> 6) + 1) << 6;
} while (pkt_start - (u8 *) urb->transfer_buffer < urb->actual_length); } while (pkt_start - (u8 *) urb->transfer_buffer < urb->actual_length);
catc->netdev->last_rx = jiffies; catc->netdev->last_rx = jiffies;
if (catc->is_f5u011) {
if (atomic_read(&catc->recq_sz)) {
int status;
atomic_dec(&catc->recq_sz);
dbg("getting extra packet");
urb->dev = catc->usbdev;
if ((status = usb_submit_urb(urb, GFP_KERNEL)) < 0) {
dbg("submit(rx_urb) status %d", status);
}
} else {
clear_bit(RX_RUNNING, &catc->flags);
}
}
} }
static void catc_irq_done(struct urb *urb) static void catc_irq_done(struct urb *urb)
...@@ -249,29 +292,48 @@ static void catc_irq_done(struct urb *urb) ...@@ -249,29 +292,48 @@ static void catc_irq_done(struct urb *urb)
struct catc *catc = urb->context; struct catc *catc = urb->context;
u8 *data = urb->transfer_buffer; u8 *data = urb->transfer_buffer;
int status; int status;
unsigned int hasdata = 0, linksts = LinkNoChange;
if (!catc->is_f5u011) {
hasdata = data[1] & 0x80;
if (data[1] & 0x40)
linksts = LinkGood;
else if (data[1] & 0x20)
linksts = LinkBad;
} else {
hasdata = (unsigned int)(be16_to_cpup((u16*)data) & 0x0fff);
if (data[0] == 0x90)
linksts = LinkGood;
else if (data[0] == 0xA0)
linksts = LinkBad;
}
if (urb->status) { if (urb->status) {
dbg("irq_done, status %d, data %02x %02x.", urb->status, data[0], data[1]); dbg("irq_done, status %d, data %02x %02x.", urb->status, data[0], data[1]);
return; return;
} }
if ((data[1] & 0x80) && !test_and_set_bit(RX_RUNNING, &catc->flags)) { if (linksts == LinkGood) {
catc->rx_urb->dev = catc->usbdev;
if ((status = usb_submit_urb(catc->rx_urb, GFP_KERNEL)) < 0) {
err("submit(rx_urb) status %d", status);
return;
}
}
if (data[1] & 0x40) {
netif_carrier_on(catc->netdev); netif_carrier_on(catc->netdev);
dbg("link ok"); dbg("link ok");
} }
if (data[1] & 0x20) { if (linksts == LinkBad) {
netif_carrier_off(catc->netdev); netif_carrier_off(catc->netdev);
dbg("link bad"); dbg("link bad");
} }
if (hasdata) {
if (test_and_set_bit(RX_RUNNING, &catc->flags)) {
if (catc->is_f5u011)
atomic_inc(&catc->recq_sz);
} else {
catc->rx_urb->dev = catc->usbdev;
if ((status = usb_submit_urb(catc->rx_urb, GFP_KERNEL)) < 0) {
err("submit(rx_urb) status %d", status);
}
}
}
} }
/* /*
...@@ -282,6 +344,9 @@ static void catc_tx_run(struct catc *catc) ...@@ -282,6 +344,9 @@ static void catc_tx_run(struct catc *catc)
{ {
int status; int status;
if (catc->is_f5u011)
catc->tx_ptr = (catc->tx_ptr + 63) & ~63;
catc->tx_urb->transfer_buffer_length = catc->tx_ptr; catc->tx_urb->transfer_buffer_length = catc->tx_ptr;
catc->tx_urb->transfer_buffer = catc->tx_buf[catc->tx_idx]; catc->tx_urb->transfer_buffer = catc->tx_buf[catc->tx_idx];
catc->tx_urb->dev = catc->usbdev; catc->tx_urb->dev = catc->usbdev;
...@@ -338,14 +403,15 @@ static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -338,14 +403,15 @@ static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
catc->tx_ptr = (((catc->tx_ptr - 1) >> 6) + 1) << 6; catc->tx_ptr = (((catc->tx_ptr - 1) >> 6) + 1) << 6;
tx_buf = catc->tx_buf[catc->tx_idx] + catc->tx_ptr; tx_buf = catc->tx_buf[catc->tx_idx] + catc->tx_ptr;
*((u16*)tx_buf) = cpu_to_le16((u16)skb->len); *((u16*)tx_buf) = (catc->is_f5u011) ? cpu_to_be16((u16)skb->len) : cpu_to_le16((u16)skb->len);
memcpy(tx_buf + 2, skb->data, skb->len); memcpy(tx_buf + 2, skb->data, skb->len);
catc->tx_ptr += skb->len + 2; catc->tx_ptr += skb->len + 2;
if (!test_and_set_bit(TX_RUNNING, &catc->flags)) if (!test_and_set_bit(TX_RUNNING, &catc->flags))
catc_tx_run(catc); catc_tx_run(catc);
if (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2))) if ((catc->is_f5u011 && catc->tx_ptr)
|| (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2))))
netif_stop_queue(netdev); netif_stop_queue(netdev);
spin_unlock_irqrestore(&catc->tx_lock, flags); spin_unlock_irqrestore(&catc->tx_lock, flags);
...@@ -554,17 +620,32 @@ static void catc_set_multicast_list(struct net_device *netdev) ...@@ -554,17 +620,32 @@ static void catc_set_multicast_list(struct net_device *netdev)
if (netdev->flags & IFF_PROMISC) { if (netdev->flags & IFF_PROMISC) {
memset(catc->multicast, 0xff, 64); memset(catc->multicast, 0xff, 64);
rx |= RxPromisc; rx |= (!catc->is_f5u011) ? RxPromisc : AltRxPromisc;
} }
if (netdev->flags & IFF_ALLMULTI) if (netdev->flags & IFF_ALLMULTI) {
memset(catc->multicast, 0xff, 64); memset(catc->multicast, 0xff, 64);
} else {
for (i = 0, mc = netdev->mc_list; mc && i < netdev->mc_count; i++, mc = mc->next) for (i = 0, mc = netdev->mc_list; mc && i < netdev->mc_count; i++, mc = mc->next) {
catc_multicast(mc->dmi_addr, catc->multicast); u32 crc = ether_crc_le(6, mc->dmi_addr);
if (!catc->is_f5u011) {
catc->multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7);
} else {
catc->multicast[7-(crc >> 29)] |= 1 << ((crc >> 26) & 7);
}
}
}
if (!catc->is_f5u011) {
catc_set_reg_async(catc, RxUnit, rx); catc_set_reg_async(catc, RxUnit, rx);
catc_write_mem_async(catc, 0xfa80, catc->multicast, 64); catc_write_mem_async(catc, 0xfa80, catc->multicast, 64);
} else {
f5u011_mchash_async(catc, catc->multicast);
if (catc->rxmode[0] != rx) {
catc->rxmode[0] = rx;
dbg("Setting RX mode to %2.2X %2.2X", catc->rxmode[0], catc->rxmode[1]);
f5u011_rxmode_async(catc, catc->rxmode);
}
}
} }
/* /*
...@@ -591,6 +672,29 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr) ...@@ -591,6 +672,29 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
/* get settings */
case ETHTOOL_GSET:
if (catc->is_f5u011) {
struct ethtool_cmd ecmd = { ETHTOOL_GSET,
SUPPORTED_10baseT_Half | SUPPORTED_TP,
ADVERTISED_10baseT_Half | ADVERTISED_TP,
SPEED_10,
DUPLEX_HALF,
PORT_TP,
0,
XCVR_INTERNAL,
AUTONEG_DISABLE,
1,
1
};
if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
return -EFAULT;
return 0;
} else {
return -EOPNOTSUPP;
}
/* get link status */ /* get link status */
case ETHTOOL_GLINK: { case ETHTOOL_GLINK: {
struct ethtool_value edata = {ETHTOOL_GLINK}; struct ethtool_value edata = {ETHTOOL_GLINK};
...@@ -632,6 +736,7 @@ static int catc_open(struct net_device *netdev) ...@@ -632,6 +736,7 @@ static int catc_open(struct net_device *netdev)
netif_start_queue(netdev); netif_start_queue(netdev);
if (!catc->is_f5u011)
mod_timer(&catc->timer, jiffies + STATS_UPDATE); mod_timer(&catc->timer, jiffies + STATS_UPDATE);
return 0; return 0;
...@@ -643,6 +748,7 @@ static int catc_stop(struct net_device *netdev) ...@@ -643,6 +748,7 @@ static int catc_stop(struct net_device *netdev)
netif_stop_queue(netdev); netif_stop_queue(netdev);
if (!catc->is_f5u011)
del_timer_sync(&catc->timer); del_timer_sync(&catc->timer);
usb_unlink_urb(catc->rx_urb); usb_unlink_urb(catc->rx_urb);
...@@ -662,7 +768,7 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str ...@@ -662,7 +768,7 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
struct net_device *netdev; struct net_device *netdev;
struct catc *catc; struct catc *catc;
u8 broadcast[6]; u8 broadcast[6];
int i; int i, pktsz;
if (usb_set_interface(usbdev, ifnum, 1)) { if (usb_set_interface(usbdev, ifnum, 1)) {
err("Can't set altsetting 1."); err("Can't set altsetting 1.");
...@@ -670,9 +776,16 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str ...@@ -670,9 +776,16 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
} }
catc = kmalloc(sizeof(struct catc), GFP_KERNEL); catc = kmalloc(sizeof(struct catc), GFP_KERNEL);
if (!catc)
return NULL;
memset(catc, 0, sizeof(struct catc)); memset(catc, 0, sizeof(struct catc));
netdev = init_etherdev(0, 0); netdev = init_etherdev(0, 0);
if (!netdev) {
kfree(catc);
return NULL;
}
netdev->open = catc_open; netdev->open = catc_open;
netdev->hard_start_xmit = catc_hard_start_xmit; netdev->hard_start_xmit = catc_hard_start_xmit;
...@@ -701,9 +814,26 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str ...@@ -701,9 +814,26 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
if ((!catc->ctrl_urb) || (!catc->tx_urb) || if ((!catc->ctrl_urb) || (!catc->tx_urb) ||
(!catc->rx_urb) || (!catc->irq_urb)) { (!catc->rx_urb) || (!catc->irq_urb)) {
err("No free urbs available."); err("No free urbs available.");
if (catc->ctrl_urb) usb_free_urb(catc->ctrl_urb);
if (catc->tx_urb) usb_free_urb(catc->tx_urb);
if (catc->rx_urb) usb_free_urb(catc->rx_urb);
if (catc->irq_urb) usb_free_urb(catc->irq_urb);
kfree(netdev);
kfree(catc);
return NULL; return NULL;
} }
/* The F5U011 has the same vendor/product as the netmate but a device version of 0x130 */
if (usbdev->descriptor.idVendor == 0x0423 && usbdev->descriptor.idProduct == 0xa &&
catc->usbdev->descriptor.bcdDevice == 0x0130 ) {
dbg("Testing for f5u011");
catc->is_f5u011 = 1;
atomic_set(&catc->recq_sz, 0);
pktsz = RX_PKT_SZ;
} else {
pktsz = RX_MAX_BURST * (PKT_SZ + 2);
}
FILL_CONTROL_URB(catc->ctrl_urb, usbdev, usb_sndctrlpipe(usbdev, 0), FILL_CONTROL_URB(catc->ctrl_urb, usbdev, usb_sndctrlpipe(usbdev, 0),
NULL, NULL, 0, catc_ctrl_done, catc); NULL, NULL, 0, catc_ctrl_done, catc);
...@@ -711,11 +841,12 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str ...@@ -711,11 +841,12 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
NULL, 0, catc_tx_done, catc); NULL, 0, catc_tx_done, catc);
FILL_BULK_URB(catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, 1), FILL_BULK_URB(catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, 1),
catc->rx_buf, RX_MAX_BURST * (PKT_SZ + 2), catc_rx_done, catc); catc->rx_buf, pktsz, catc_rx_done, catc);
FILL_INT_URB(catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, 2), FILL_INT_URB(catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, 2),
catc->irq_buf, 2, catc_irq_done, catc, 1); catc->irq_buf, 2, catc_irq_done, catc, 1);
if (!catc->is_f5u011) {
dbg("Checking memory size\n"); dbg("Checking memory size\n");
i = 0x12345678; i = 0x12345678;
...@@ -750,7 +881,7 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str ...@@ -750,7 +881,7 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
dbg("Filling the multicast list."); dbg("Filling the multicast list.");
memset(broadcast, 0xff, 8); memset(broadcast, 0xff, 6);
catc_multicast(broadcast, catc->multicast); catc_multicast(broadcast, catc->multicast);
catc_multicast(netdev->dev_addr, catc->multicast); catc_multicast(netdev->dev_addr, catc->multicast);
catc_write_mem(catc, 0xfa80, catc->multicast, 64); catc_write_mem(catc, 0xfa80, catc->multicast, 64);
...@@ -767,14 +898,22 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str ...@@ -767,14 +898,22 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
catc_set_reg(catc, OpModes, OpTxMerge | OpRxMerge | OpLenInclude | Op3MemWaits); catc_set_reg(catc, OpModes, OpTxMerge | OpRxMerge | OpLenInclude | Op3MemWaits);
catc_set_reg(catc, LEDCtrl, LEDLink); catc_set_reg(catc, LEDCtrl, LEDLink);
catc_set_reg(catc, RxUnit, RxEnable | RxPolarity | RxMultiCast); catc_set_reg(catc, RxUnit, RxEnable | RxPolarity | RxMultiCast);
} else {
dbg("Performing reset\n");
catc_reset(catc);
catc_get_mac(catc, netdev->dev_addr);
dbg("Setting RX Mode");
catc->rxmode[0] = RxEnable | RxPolarity | RxMultiCast;
catc->rxmode[1] = 0;
f5u011_rxmode(catc, catc->rxmode);
}
dbg("Init done."); dbg("Init done.");
printk(KERN_INFO "%s: %s USB Ethernet at usb%d:%d.%d, ",
printk(KERN_INFO "%s: CATC EL1210A NetMate USB Ethernet at usb%d:%d.%d, ", netdev->name, (catc->is_f5u011) ? "Belkin F5U011" : "CATC EL1210A NetMate",
netdev->name, usbdev->bus->busnum, usbdev->devnum, ifnum); usbdev->bus->busnum, usbdev->devnum, ifnum);
for (i = 0; i < 5; i++) printk("%2.2x:", netdev->dev_addr[i]); for (i = 0; i < 5; i++) printk("%2.2x:", netdev->dev_addr[i]);
printk("%2.2x.\n", netdev->dev_addr[i]); printk("%2.2x.\n", netdev->dev_addr[i]);
return catc; return catc;
} }
...@@ -795,7 +934,7 @@ static void catc_disconnect(struct usb_device *usbdev, void *dev_ptr) ...@@ -795,7 +934,7 @@ static void catc_disconnect(struct usb_device *usbdev, void *dev_ptr)
*/ */
static struct usb_device_id catc_id_table [] = { static struct usb_device_id catc_id_table [] = {
{ USB_DEVICE(0x0423, 0xa) }, /* CATC Netmate */ { USB_DEVICE(0x0423, 0xa) }, /* CATC Netmate, Belkin F5U011 */
{ USB_DEVICE(0x0423, 0xc) }, /* CATC Netmate II, Belkin F5U111 */ { USB_DEVICE(0x0423, 0xc) }, /* CATC Netmate II, Belkin F5U111 */
{ USB_DEVICE(0x08d1, 0x1) }, /* smartBridges smartNIC */ { USB_DEVICE(0x08d1, 0x1) }, /* smartBridges smartNIC */
{ } { }
......
...@@ -110,10 +110,11 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned ...@@ -110,10 +110,11 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
memset(field, 0, sizeof(struct hid_field) + usages * sizeof(struct hid_usage) memset(field, 0, sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
+ values * sizeof(unsigned)); + values * sizeof(unsigned));
report->field[report->maxfield++] = field; report->field[report->maxfield] = field;
field->usage = (struct hid_usage *)(field + 1); field->usage = (struct hid_usage *)(field + 1);
field->value = (unsigned *)(field->usage + usages); field->value = (unsigned *)(field->usage + usages);
field->report = report; field->report = report;
field->index = report->maxfield++;
return field; return field;
} }
...@@ -741,8 +742,20 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field, s ...@@ -741,8 +742,20 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field, s
if (hid->claimed & HID_CLAIMED_INPUT) if (hid->claimed & HID_CLAIMED_INPUT)
hidinput_hid_event(hid, field, usage, value); hidinput_hid_event(hid, field, usage, value);
#ifdef CONFIG_USB_HIDDEV #ifdef CONFIG_USB_HIDDEV
if (hid->claimed & HID_CLAIMED_HIDDEV) if (hid->claimed & HID_CLAIMED_HIDDEV) {
hiddev_hid_event(hid, usage->hid, value); struct hiddev_usage_ref uref;
unsigned type = field->report_type;
uref.report_type =
(type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT :
((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0));
uref.report_id = field->report->id;
uref.field_index = field->index;
uref.usage_index = (usage - field->usage);
uref.usage_code = usage->hid;
uref.value = value;
hiddev_hid_event(hid, &uref);
}
#endif #endif
} }
...@@ -839,6 +852,21 @@ static int hid_input_report(int type, struct urb *urb) ...@@ -839,6 +852,21 @@ static int hid_input_report(int type, struct urb *urb)
return -1; return -1;
} }
#ifdef CONFIG_USB_HIDDEV
/* Notify listeners that a report has been received */
if (hid->claimed & HID_CLAIMED_HIDDEV) {
struct hiddev_usage_ref uref;
memset(&uref, 0, sizeof(uref));
uref.report_type =
(type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT :
((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0));
uref.report_id = report->id;
uref.field_index = HID_FIELD_INDEX_NONE;
hiddev_hid_event(hid, &uref);
}
#endif
size = ((report->size - 1) >> 3) + 1; size = ((report->size - 1) >> 3) + 1;
if (len < size) { if (len < size) {
...@@ -1096,6 +1124,9 @@ void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsign ...@@ -1096,6 +1124,9 @@ void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsign
int head; int head;
unsigned long flags; unsigned long flags;
if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)
return;
if (hid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) { if (hid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {
spin_lock_irqsave(&hid->outlock, flags); spin_lock_irqsave(&hid->outlock, flags);
...@@ -1238,18 +1269,27 @@ void hid_init_reports(struct hid_device *hid) ...@@ -1238,18 +1269,27 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_POWERMATE 0x0410 #define USB_DEVICE_ID_POWERMATE 0x0410
#define USB_DEVICE_ID_SOUNDKNOB 0x04AA #define USB_DEVICE_ID_SOUNDKNOB 0x04AA
#define USB_VENDOR_ID_ATEN 0x0557
#define USB_DEVICE_ID_ATEN_UC100KM 0x2004
#define USB_DEVICE_ID_ATEN_CS124U 0x2202
#define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204
struct hid_blacklist { struct hid_blacklist {
__u16 idVendor; __u16 idVendor;
__u16 idProduct; __u16 idProduct;
unsigned quirks;
} hid_blacklist[] = { } hid_blacklist[] = {
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE }, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS }, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1}, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2}, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3}, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4}, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE }, { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB }, { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
{ 0, 0 } { 0, 0 }
}; };
...@@ -1258,13 +1298,17 @@ static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum) ...@@ -1258,13 +1298,17 @@ static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum)
struct usb_interface_descriptor *interface = dev->actconfig->interface[ifnum].altsetting + 0; struct usb_interface_descriptor *interface = dev->actconfig->interface[ifnum].altsetting + 0;
struct hid_descriptor *hdesc; struct hid_descriptor *hdesc;
struct hid_device *hid; struct hid_device *hid;
unsigned rsize = 0; unsigned quirks = 0, rsize = 0;
char *buf; char *buf;
int n; int n;
for (n = 0; hid_blacklist[n].idVendor; n++) for (n = 0; hid_blacklist[n].idVendor; n++)
if ((hid_blacklist[n].idVendor == dev->descriptor.idVendor) && if ((hid_blacklist[n].idVendor == dev->descriptor.idVendor) &&
(hid_blacklist[n].idProduct == dev->descriptor.idProduct)) return NULL; (hid_blacklist[n].idProduct == dev->descriptor.idProduct))
quirks = hid_blacklist[n].quirks;
if (quirks & HID_QUIRK_IGNORE)
return NULL;
if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && ((!interface->bNumEndpoints) || if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && ((!interface->bNumEndpoints) ||
usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) { usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
...@@ -1302,6 +1346,8 @@ static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum) ...@@ -1302,6 +1346,8 @@ static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum)
} }
} }
hid->quirks = quirks;
for (n = 0; n < interface->bNumEndpoints; n++) { for (n = 0; n < interface->bNumEndpoints; n++) {
struct usb_endpoint_descriptor *endpoint = &interface->endpoint[n]; struct usb_endpoint_descriptor *endpoint = &interface->endpoint[n];
......
...@@ -203,6 +203,8 @@ struct hid_item { ...@@ -203,6 +203,8 @@ struct hid_item {
#define HID_QUIRK_INVERT 0x01 #define HID_QUIRK_INVERT 0x01
#define HID_QUIRK_NOTOUCH 0x02 #define HID_QUIRK_NOTOUCH 0x02
#define HID_QUIRK_IGNORE 0x04
#define HID_QUIRK_NOGET 0x08
/* /*
* This is the global enviroment of the parser. This information is * This is the global enviroment of the parser. This information is
...@@ -276,6 +278,7 @@ struct hid_field { ...@@ -276,6 +278,7 @@ struct hid_field {
__s32 unit_exponent; __s32 unit_exponent;
unsigned unit; unsigned unit;
struct hid_report *report; /* associated report */ struct hid_report *report; /* associated report */
unsigned index; /* index into report->field[] */
}; };
#define HID_MAX_FIELDS 64 #define HID_MAX_FIELDS 64
......
...@@ -50,9 +50,10 @@ struct hiddev { ...@@ -50,9 +50,10 @@ struct hiddev {
}; };
struct hiddev_list { struct hiddev_list {
struct hiddev_event buffer[HIDDEV_BUFFER_SIZE]; struct hiddev_usage_ref buffer[HIDDEV_BUFFER_SIZE];
int head; int head;
int tail; int tail;
unsigned flags;
struct fasync_struct *fasync; struct fasync_struct *fasync;
struct hiddev *hiddev; struct hiddev *hiddev;
struct hiddev_list *next; struct hiddev_list *next;
...@@ -146,17 +147,19 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref) ...@@ -146,17 +147,19 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref)
* This is where hid.c calls into hiddev to pass an event that occurred over * This is where hid.c calls into hiddev to pass an event that occurred over
* the interrupt pipe * the interrupt pipe
*/ */
void hiddev_hid_event(struct hid_device *hid, unsigned int usage, int value) void hiddev_hid_event(struct hid_device *hid, struct hiddev_usage_ref *uref)
{ {
struct hiddev *hiddev = hid->hiddev; struct hiddev *hiddev = hid->hiddev;
struct hiddev_list *list = hiddev->list; struct hiddev_list *list = hiddev->list;
while (list) { while (list) {
list->buffer[list->head].hid = usage; if (uref->field_index != HID_FIELD_INDEX_NONE ||
list->buffer[list->head].value = value; (list->flags & HIDDEV_FLAG_REPORT) != 0) {
list->head = (list->head + 1) & (HIDDEV_BUFFER_SIZE - 1); list->buffer[list->head] = *uref;
list->head = (list->head + 1) &
(HIDDEV_BUFFER_SIZE - 1);
kill_fasync(&list->fasync, SIGIO, POLL_IN); kill_fasync(&list->fasync, SIGIO, POLL_IN);
}
list = list->next; list = list->next;
} }
...@@ -257,15 +260,20 @@ static ssize_t hiddev_read(struct file * file, char * buffer, size_t count, ...@@ -257,15 +260,20 @@ static ssize_t hiddev_read(struct file * file, char * buffer, size_t count,
{ {
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
struct hiddev_list *list = file->private_data; struct hiddev_list *list = file->private_data;
int event_size;
int retval = 0; int retval = 0;
if (list->head == list->tail) { event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ?
sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event);
if (count < event_size) return 0;
while (retval == 0) {
if (list->head == list->tail) {
add_wait_queue(&list->hiddev->wait, &wait); add_wait_queue(&list->hiddev->wait, &wait);
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
while (list->head == list->tail) { while (list->head == list->tail) {
if (file->f_flags & O_NONBLOCK) { if (file->f_flags & O_NONBLOCK) {
retval = -EAGAIN; retval = -EAGAIN;
break; break;
...@@ -289,12 +297,31 @@ static ssize_t hiddev_read(struct file * file, char * buffer, size_t count, ...@@ -289,12 +297,31 @@ static ssize_t hiddev_read(struct file * file, char * buffer, size_t count,
if (retval) if (retval)
return retval; return retval;
while (list->head != list->tail && retval + sizeof(struct hiddev_event) <= count) {
if (copy_to_user(buffer + retval, list->buffer + list->tail, while (list->head != list->tail &&
sizeof(struct hiddev_event))) return -EFAULT; retval + event_size <= count) {
list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1); if ((list->flags & HIDDEV_FLAG_UREF) == 0) {
if (list->buffer[list->tail].field_index !=
HID_FIELD_INDEX_NONE) {
struct hiddev_event event;
event.hid = list->buffer[list->tail].usage_code;
event.value = list->buffer[list->tail].value;
if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event)))
return -EFAULT;
retval += sizeof(struct hiddev_event); retval += sizeof(struct hiddev_event);
} }
} else {
if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE ||
(list->flags & HIDDEV_FLAG_REPORT) != 0) {
if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref)))
return -EFAULT;
retval += sizeof(struct hiddev_usage_ref);
}
}
list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1);
}
}
return retval; return retval;
} }
...@@ -358,6 +385,25 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, ...@@ -358,6 +385,25 @@ static int hiddev_ioctl(struct inode *inode, struct file *file,
return copy_to_user((void *) arg, &dinfo, sizeof(dinfo)); return copy_to_user((void *) arg, &dinfo, sizeof(dinfo));
} }
case HIDIOCGFLAG:
return put_user(list->flags, (int *) arg);
case HIDIOCSFLAG:
{
int newflags;
if (get_user(newflags, (int *) arg))
return -EFAULT;
if ((newflags & ~HIDDEV_FLAGS) != 0 ||
((newflags & HIDDEV_FLAG_REPORT) != 0 &&
(newflags & HIDDEV_FLAG_UREF) == 0))
return -EINVAL;
list->flags = newflags;
return 0;
}
case HIDIOCGSTRING: case HIDIOCGSTRING:
{ {
int idx, len; int idx, len;
......
/* /*
* printer.c Version 0.8 * printer.c Version 0.12
* *
* Copyright (c) 1999 Michael Gee <michael@linuxspecific.com> * Copyright (c) 1999 Michael Gee <michael@linuxspecific.com>
* Copyright (c) 1999 Pavel Machek <pavel@suse.cz> * Copyright (c) 1999 Pavel Machek <pavel@suse.cz>
* Copyright (c) 2000 Randy Dunlap <randy.dunlap@intel.com> * Copyright (c) 2000 Randy Dunlap <randy.dunlap@intel.com>
* Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz> * Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
# Copyright (c) 2001 Pete Zaitcev <zaitcev@redhat.com>
# Copyright (c) 2001 David Paschal <paschal@rcsis.com>
* *
* USB Printer Device Class driver for USB printers and printer cables * USB Printer Device Class driver for USB printers and printer cables
* *
...@@ -17,10 +19,12 @@ ...@@ -17,10 +19,12 @@
* v0.4 - fixes in unidirectional mode * v0.4 - fixes in unidirectional mode
* v0.5 - add DEVICE_ID string support * v0.5 - add DEVICE_ID string support
* v0.6 - never time out * v0.6 - never time out
* v0.7 - fixed bulk-IN read and poll (David Paschal, paschal@rcsis.com) * v0.7 - fixed bulk-IN read and poll (David Paschal)
* v0.8 - add devfs support * v0.8 - add devfs support
* v0.9 - fix unplug-while-open paths * v0.9 - fix unplug-while-open paths
* v0.10- remove sleep_on, fix error on oom (oliver@neukum.org) * v0.10- remove sleep_on, fix error on oom (oliver@neukum.org)
* v0.11 - add proto_bias option (Pete Zaitcev)
* v0.12 - add hpoj.sourceforge.net ioctls (David Paschal)
*/ */
/* /*
...@@ -55,16 +59,36 @@ ...@@ -55,16 +59,36 @@
/* /*
* Version Information * Version Information
*/ */
#define DRIVER_VERSION "v0.10" #define DRIVER_VERSION "v0.12"
#define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap" #define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap, Pete Zaitcev, David Paschal"
#define DRIVER_DESC "USB Printer Device Class driver" #define DRIVER_DESC "USB Printer Device Class driver"
#define USBLP_BUF_SIZE 8192 #define USBLP_BUF_SIZE 8192
#define DEVICE_ID_SIZE 1024 #define DEVICE_ID_SIZE 1024
#define IOCNR_GET_DEVICE_ID 1 /* ioctls: */
#define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len) /* get device_id string */
#define LPGETSTATUS 0x060b /* same as in drivers/char/lp.c */ #define LPGETSTATUS 0x060b /* same as in drivers/char/lp.c */
#define IOCNR_GET_DEVICE_ID 1
#define IOCNR_GET_PROTOCOLS 2
#define IOCNR_SET_PROTOCOL 3
#define IOCNR_HP_SET_CHANNEL 4
#define IOCNR_GET_BUS_ADDRESS 5
#define IOCNR_GET_VID_PID 6
/* Get device_id string: */
#define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len)
/* The following ioctls were added for http://hpoj.sourceforge.net: */
/* Get two-int array:
* [0]=current protocol (1=7/1/1, 2=7/1/2, 3=7/1/3),
* [1]=supported protocol mask (mask&(1<<n)!=0 means 7/1/n supported): */
#define LPIOC_GET_PROTOCOLS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_PROTOCOLS, len)
/* Set protocol (arg: 1=7/1/1, 2=7/1/2, 3=7/1/3): */
#define LPIOC_SET_PROTOCOL _IOC(_IOC_WRITE, 'P', IOCNR_SET_PROTOCOL, 0)
/* Set channel number (HP Vendor-specific command): */
#define LPIOC_HP_SET_CHANNEL _IOC(_IOC_WRITE, 'P', IOCNR_HP_SET_CHANNEL, 0)
/* Get two-int array: [0]=bus number, [1]=device address: */
#define LPIOC_GET_BUS_ADDRESS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_BUS_ADDRESS, len)
/* Get two-int array: [0]=vendor ID, [1]=product ID: */
#define LPIOC_GET_VID_PID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_VID_PID, len)
/* /*
* A DEVICE_ID string may include the printer's serial number. * A DEVICE_ID string may include the printer's serial number.
...@@ -81,20 +105,34 @@ MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:H ...@@ -81,20 +105,34 @@ MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:H
#define USBLP_REQ_GET_ID 0x00 #define USBLP_REQ_GET_ID 0x00
#define USBLP_REQ_GET_STATUS 0x01 #define USBLP_REQ_GET_STATUS 0x01
#define USBLP_REQ_RESET 0x02 #define USBLP_REQ_RESET 0x02
#define USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST 0x00 /* HP Vendor-specific */
#define USBLP_MINORS 16 #define USBLP_MINORS 16
#define USBLP_MINOR_BASE 0 #define USBLP_MINOR_BASE 0
#define USBLP_WRITE_TIMEOUT (5*HZ) /* 5 seconds */ #define USBLP_WRITE_TIMEOUT (5*HZ) /* 5 seconds */
#define USBLP_FIRST_PROTOCOL 1
#define USBLP_LAST_PROTOCOL 3
#define USBLP_MAX_PROTOCOLS (USBLP_LAST_PROTOCOL+1)
struct usblp { struct usblp {
struct usb_device *dev; /* USB device */ struct usb_device *dev; /* USB device */
devfs_handle_t devfs; /* devfs device */ devfs_handle_t devfs; /* devfs device */
struct semaphore sem; /* locks this struct, especially "dev" */ struct semaphore sem; /* locks this struct, especially "dev" */
char *buf; /* writeurb->transfer_buffer */
struct urb *readurb, *writeurb; /* The urbs */ struct urb *readurb, *writeurb; /* The urbs */
wait_queue_head_t wait; /* Zzzzz ... */ wait_queue_head_t wait; /* Zzzzz ... */
int readcount; /* Counter for reads */ int readcount; /* Counter for reads */
int ifnum; /* Interface number */ int ifnum; /* Interface number */
/* Alternate-setting numbers and endpoints for each protocol
* (7/1/{index=1,2,3}) that the device supports: */
struct {
int alt_setting;
struct usb_endpoint_descriptor *epwrite;
struct usb_endpoint_descriptor *epread;
} protocol[USBLP_MAX_PROTOCOLS];
int current_protocol;
int minor; /* minor number of device */ int minor; /* minor number of device */
int wcomplete; /* writing is completed */ int wcomplete; /* writing is completed */
int rcomplete; /* reading is completed */ int rcomplete; /* reading is completed */
...@@ -105,6 +143,35 @@ struct usblp { ...@@ -105,6 +143,35 @@ struct usblp {
/* first 2 bytes are (big-endian) length */ /* first 2 bytes are (big-endian) length */
}; };
#ifdef DEBUG
static void usblp_dump(struct usblp *usblp) {
int p;
dbg("usblp=0x%p", usblp);
dbg("dev=0x%p", usblp->dev);
dbg("devfs=0x%p", usblp->devfs);
dbg("buf=0x%p", usblp->buf);
dbg("readcount=%d", usblp->readcount);
dbg("ifnum=%d", usblp->ifnum);
for (p = USBLP_FIRST_PROTOCOL; p <= USBLP_LAST_PROTOCOL; p++) {
dbg("protocol[%d].alt_setting=%d", p, usblp->protocol[p].alt_setting);
dbg("protocol[%d].epwrite=%p", p, usblp->protocol[p].epwrite);
dbg("protocol[%d].epread=%p", p, usblp->protocol[p].epread);
}
dbg("current_protocol=%d", usblp->current_protocol);
dbg("minor=%d", usblp->minor);
dbg("wcomplete=%d", usblp->wcomplete);
dbg("rcomplete=%d", usblp->rcomplete);
dbg("quirks=%d", usblp->quirks);
dbg("used=%d", usblp->used);
dbg("bidir=%d", usblp->bidir);
dbg("device_id_string=\"%s\"",
usblp->device_id_string ?
usblp->device_id_string + 2 :
(unsigned char *)"(null)");
}
#endif
extern devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */ extern devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */
static struct usblp *usblp_table[USBLP_MINORS]; static struct usblp *usblp_table[USBLP_MINORS];
...@@ -126,29 +193,45 @@ static struct quirk_printer_struct quirk_printers[] = { ...@@ -126,29 +193,45 @@ static struct quirk_printer_struct quirk_printers[] = {
{ 0x03f0, 0x0204, USBLP_QUIRK_BIDIR }, /* HP DeskJet 815C */ { 0x03f0, 0x0204, USBLP_QUIRK_BIDIR }, /* HP DeskJet 815C */
{ 0x03f0, 0x0304, USBLP_QUIRK_BIDIR }, /* HP DeskJet 810C/812C */ { 0x03f0, 0x0304, USBLP_QUIRK_BIDIR }, /* HP DeskJet 810C/812C */
{ 0x03f0, 0x0404, USBLP_QUIRK_BIDIR }, /* HP DeskJet 830C */ { 0x03f0, 0x0404, USBLP_QUIRK_BIDIR }, /* HP DeskJet 830C */
{ 0x0409, 0xefbe, USBLP_QUIRK_BIDIR }, /* NEC Picty900 (HP OEM) */
{ 0, 0 } { 0, 0 }
}; };
static int usblp_select_alts(struct usblp *usblp);
static int usblp_set_protocol(struct usblp *usblp, int protocol);
static int usblp_cache_device_id_string(struct usblp *usblp);
/* /*
* Functions for usblp control messages. * Functions for usblp control messages.
*/ */
static int usblp_ctrl_msg(struct usblp *usblp, int request, int dir, int recip, int value, void *buf, int len) static int usblp_ctrl_msg(struct usblp *usblp, int request, int type, int dir, int recip, int value, void *buf, int len)
{ {
int retval = usb_control_msg(usblp->dev, int retval = usb_control_msg(usblp->dev,
dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0), dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0),
request, USB_TYPE_CLASS | dir | recip, value, usblp->ifnum, buf, len, HZ * 5); request, type | dir | recip, value, usblp->ifnum, buf, len, USBLP_WRITE_TIMEOUT);
dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d len: %#x result: %d", dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d len: %#x result: %d",
request, !!dir, recip, value, len, retval); request, !!dir, recip, value, len, retval);
return retval < 0 ? retval : 0; return retval < 0 ? retval : 0;
} }
#define usblp_read_status(usblp, status)\ #define usblp_read_status(usblp, status)\
usblp_ctrl_msg(usblp, USBLP_REQ_GET_STATUS, USB_DIR_IN, USB_RECIP_INTERFACE, 0, status, 1) usblp_ctrl_msg(usblp, USBLP_REQ_GET_STATUS, USB_TYPE_CLASS, USB_DIR_IN, USB_RECIP_INTERFACE, 0, status, 1)
#define usblp_get_id(usblp, config, id, maxlen)\ #define usblp_get_id(usblp, config, id, maxlen)\
usblp_ctrl_msg(usblp, USBLP_REQ_GET_ID, USB_DIR_IN, USB_RECIP_INTERFACE, config, id, maxlen) usblp_ctrl_msg(usblp, USBLP_REQ_GET_ID, USB_TYPE_CLASS, USB_DIR_IN, USB_RECIP_INTERFACE, config, id, maxlen)
#define usblp_reset(usblp)\ #define usblp_reset(usblp)\
usblp_ctrl_msg(usblp, USBLP_REQ_RESET, USB_DIR_OUT, USB_RECIP_OTHER, 0, NULL, 0) usblp_ctrl_msg(usblp, USBLP_REQ_RESET, USB_TYPE_CLASS, USB_DIR_OUT, USB_RECIP_OTHER, 0, NULL, 0)
#define usblp_hp_channel_change_request(usblp, channel, buffer) \
usblp_ctrl_msg(usblp, USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST, USB_TYPE_VENDOR, USB_DIR_IN, USB_RECIP_INTERFACE, channel, buffer, 1)
/*
* See the description for usblp_select_alts() below for the usage
* explanation. Look into your /proc/bus/usb/devices and dmesg in
* case of any trouble.
*/
static int proto_bias = -1;
/* /*
* URB callback. * URB callback.
...@@ -276,7 +359,7 @@ static void usblp_cleanup (struct usblp *usblp) ...@@ -276,7 +359,7 @@ static void usblp_cleanup (struct usblp *usblp)
{ {
devfs_unregister (usblp->devfs); devfs_unregister (usblp->devfs);
usblp_table [usblp->minor] = NULL; usblp_table [usblp->minor] = NULL;
info ("usblp%d: removed", usblp->minor); info("usblp%d: removed", usblp->minor);
kfree (usblp->writeurb->transfer_buffer); kfree (usblp->writeurb->transfer_buffer);
kfree (usblp->device_id_string); kfree (usblp->device_id_string);
...@@ -285,6 +368,13 @@ static void usblp_cleanup (struct usblp *usblp) ...@@ -285,6 +368,13 @@ static void usblp_cleanup (struct usblp *usblp)
kfree (usblp); kfree (usblp);
} }
static void usblp_unlink_urbs(struct usblp *usblp)
{
usb_unlink_urb(usblp->writeurb);
if (usblp->bidir)
usb_unlink_urb(usblp->readurb);
}
static int usblp_release(struct inode *inode, struct file *file) static int usblp_release(struct inode *inode, struct file *file)
{ {
struct usblp *usblp = file->private_data; struct usblp *usblp = file->private_data;
...@@ -293,9 +383,7 @@ static int usblp_release(struct inode *inode, struct file *file) ...@@ -293,9 +383,7 @@ static int usblp_release(struct inode *inode, struct file *file)
lock_kernel(); lock_kernel();
usblp->used = 0; usblp->used = 0;
if (usblp->dev) { if (usblp->dev) {
if (usblp->bidir) usblp_unlink_urbs(usblp);
usb_unlink_urb(usblp->readurb);
usb_unlink_urb(usblp->writeurb);
up(&usblp->sem); up(&usblp->sem);
} else /* finish cleanup from disconnect */ } else /* finish cleanup from disconnect */
usblp_cleanup (usblp); usblp_cleanup (usblp);
...@@ -315,8 +403,9 @@ static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait ...@@ -315,8 +403,9 @@ static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait
static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{ {
struct usblp *usblp = file->private_data; struct usblp *usblp = file->private_data;
int length, err; int length, err, i;
unsigned char status; unsigned char status, newChannel;
int twoints[2];
int retval = 0; int retval = 0;
down (&usblp->sem); down (&usblp->sem);
...@@ -335,32 +424,128 @@ static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -335,32 +424,128 @@ static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
goto done; goto done;
} }
err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1); length = usblp_cache_device_id_string(usblp);
if (length < 0) {
retval = length;
goto done;
}
if (length > _IOC_SIZE(cmd))
length = _IOC_SIZE(cmd); /* truncate */
if (copy_to_user((unsigned char *) arg,
usblp->device_id_string,
(unsigned long) length)) {
retval = -EFAULT;
goto done;
}
break;
case IOCNR_GET_PROTOCOLS:
if (_IOC_DIR(cmd) != _IOC_READ ||
_IOC_SIZE(cmd) < sizeof(twoints)) {
retval = -EINVAL;
goto done;
}
twoints[0] = usblp->current_protocol;
twoints[1] = 0;
for (i = USBLP_FIRST_PROTOCOL;
i <= USBLP_LAST_PROTOCOL; i++) {
if (usblp->protocol[i].alt_setting >= 0)
twoints[1] |= (1<<i);
}
if (copy_to_user((unsigned char *)arg,
(unsigned char *)twoints,
sizeof(twoints))) {
retval = -EFAULT;
goto done;
}
break;
case IOCNR_SET_PROTOCOL:
if (_IOC_DIR(cmd) != _IOC_WRITE) {
retval = -EINVAL;
goto done;
}
#ifdef DEBUG
if (arg == -10) {
usblp_dump(usblp);
break;
}
#endif
usblp_unlink_urbs(usblp);
retval = usblp_set_protocol(usblp, arg);
if (retval < 0) {
usblp_set_protocol(usblp,
usblp->current_protocol);
}
break;
case IOCNR_HP_SET_CHANNEL:
if (_IOC_DIR(cmd) != _IOC_WRITE ||
usblp->dev->descriptor.idVendor != 0x03F0 ||
usblp->quirks & USBLP_QUIRK_BIDIR) {
retval = -EINVAL;
goto done;
}
err = usblp_hp_channel_change_request(usblp,
arg, &newChannel);
if (err < 0) { if (err < 0) {
dbg ("usblp%d: error = %d reading IEEE-1284 Device ID string", err("usblp%d: error = %d setting "
"HP channel",
usblp->minor, err); usblp->minor, err);
usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
retval = -EIO; retval = -EIO;
goto done; goto done;
} }
length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1]; /* big-endian */ dbg("usblp%d requested/got HP channel %ld/%d",
if (length < DEVICE_ID_SIZE) usblp->minor, arg, newChannel);
usblp->device_id_string[length] = '\0'; break;
else
usblp->device_id_string[DEVICE_ID_SIZE - 1] = '\0';
dbg ("usblp%d Device ID string [%d/max %d]='%s'", case IOCNR_GET_BUS_ADDRESS:
usblp->minor, length, _IOC_SIZE(cmd), &usblp->device_id_string[2]); if (_IOC_DIR(cmd) != _IOC_READ ||
_IOC_SIZE(cmd) < sizeof(twoints)) {
retval = -EINVAL;
goto done;
}
if (length > _IOC_SIZE(cmd)) length = _IOC_SIZE(cmd); /* truncate */ twoints[0] = usblp->dev->bus->busnum;
twoints[1] = usblp->dev->devnum;
if (copy_to_user((unsigned char *)arg,
(unsigned char *)twoints,
sizeof(twoints))) {
retval = -EFAULT;
goto done;
}
if (copy_to_user((unsigned char *) arg, dbg("usblp%d is bus=%d, device=%d",
usblp->device_id_string, (unsigned long) length)) { usblp->minor, twoints[0], twoints[1]);
break;
case IOCNR_GET_VID_PID:
if (_IOC_DIR(cmd) != _IOC_READ ||
_IOC_SIZE(cmd) < sizeof(twoints)) {
retval = -EINVAL;
goto done;
}
twoints[0] = usblp->dev->descriptor.idVendor;
twoints[1] = usblp->dev->descriptor.idProduct;
if (copy_to_user((unsigned char *)arg,
(unsigned char *)twoints,
sizeof(twoints))) {
retval = -EFAULT; retval = -EFAULT;
goto done; goto done;
} }
dbg("usblp%d is VID=0x%4.4X, PID=0x%4.4X",
usblp->minor, twoints[0], twoints[1]);
break; break;
default: default:
...@@ -593,155 +778,268 @@ static struct file_operations usblp_fops = { ...@@ -593,155 +778,268 @@ static struct file_operations usblp_fops = {
static void *usblp_probe(struct usb_device *dev, unsigned int ifnum, static void *usblp_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
struct usb_interface_descriptor *interface; struct usblp *usblp = 0;
struct usb_endpoint_descriptor *epread, *epwrite; int protocol;
struct usblp *usblp;
int minor, i, bidir = 0, quirks;
int alts = dev->actconfig->interface[ifnum].act_altsetting;
int length, err;
char *buf;
char name[6]; char name[6];
/* If a bidirectional interface exists, use it. */ /* Malloc and start initializing usblp structure so we can use it
for (i = 0; i < dev->actconfig->interface[ifnum].num_altsetting; i++) { * directly. */
interface = &dev->actconfig->interface[ifnum].altsetting[i];
if (interface->bInterfaceClass != 7 || interface->bInterfaceSubClass != 1 ||
interface->bInterfaceProtocol < 1 || interface->bInterfaceProtocol > 3 ||
(interface->bInterfaceProtocol > 1 && interface->bNumEndpoints < 2))
continue;
if (interface->bInterfaceProtocol > 1) {
bidir = 1;
alts = i;
break;
}
}
interface = &dev->actconfig->interface[ifnum].altsetting[alts];
if (usb_set_interface(dev, ifnum, alts))
err("can't set desired altsetting %d on interface %d", alts, ifnum);
epwrite = interface->endpoint + 0;
epread = bidir ? interface->endpoint + 1 : NULL;
if ((epwrite->bEndpointAddress & 0x80) == 0x80) {
if (interface->bNumEndpoints == 1)
return NULL;
epwrite = interface->endpoint + 1;
epread = bidir ? interface->endpoint + 0 : NULL;
}
if ((epwrite->bEndpointAddress & 0x80) == 0x80)
return NULL;
if (bidir && (epread->bEndpointAddress & 0x80) != 0x80)
return NULL;
for (minor = 0; minor < USBLP_MINORS && usblp_table[minor]; minor++);
if (usblp_table[minor]) {
err("no more free usblp devices");
return NULL;
}
if (!(usblp = kmalloc(sizeof(struct usblp), GFP_KERNEL))) { if (!(usblp = kmalloc(sizeof(struct usblp), GFP_KERNEL))) {
err("out of memory"); err("out of memory for usblp");
return NULL; goto abort;
} }
memset(usblp, 0, sizeof(struct usblp)); memset(usblp, 0, sizeof(struct usblp));
init_MUTEX (&usblp->sem);
/* lookup quirks for this printer */
quirks = usblp_quirks(dev->descriptor.idVendor, dev->descriptor.idProduct);
if (bidir && (quirks & USBLP_QUIRK_BIDIR)) {
bidir = 0;
epread = NULL;
info ("Disabling reads from problem bidirectional printer on usblp%d",
minor);
}
usblp->dev = dev; usblp->dev = dev;
init_MUTEX (&usblp->sem);
init_waitqueue_head(&usblp->wait);
usblp->ifnum = ifnum; usblp->ifnum = ifnum;
usblp->minor = minor;
usblp->bidir = bidir;
usblp->quirks = quirks;
init_waitqueue_head(&usblp->wait); /* Look for a free usblp_table entry. */
while (usblp_table[usblp->minor]) {
usblp->minor++;
if (usblp->minor >= USBLP_MINORS) {
err("no more free usblp devices");
goto abort;
}
}
usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL); usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL);
if (!usblp->writeurb) { if (!usblp->writeurb) {
err("out of memory"); err("out of memory");
kfree(usblp); goto abort;
return NULL;
} }
usblp->readurb = usb_alloc_urb(0, GFP_KERNEL); usblp->readurb = usb_alloc_urb(0, GFP_KERNEL);
if (!usblp->readurb) { if (!usblp->readurb) {
err("out of memory"); err("out of memory");
usb_free_urb(usblp->writeurb); goto abort;
kfree(usblp);
return NULL;
} }
if (!(buf = kmalloc(USBLP_BUF_SIZE * (bidir ? 2 : 1), GFP_KERNEL))) { /* Malloc device ID string buffer to the largest expected length,
err("out of memory"); * since we can re-query it on an ioctl and a dynamic string
usb_free_urb(usblp->writeurb); * could change in length. */
usb_free_urb(usblp->readurb); if (!(usblp->device_id_string = kmalloc(DEVICE_ID_SIZE, GFP_KERNEL))) {
kfree(usblp); err("out of memory for device_id_string");
return NULL; goto abort;
} }
if (!(usblp->device_id_string = kmalloc(DEVICE_ID_SIZE, GFP_KERNEL))) { /* Malloc write/read buffers in one chunk. We somewhat wastefully
err("out of memory"); * malloc both regardless of bidirectionality, because the
usb_free_urb(usblp->writeurb); * alternate setting can be changed later via an ioctl. */
usb_free_urb(usblp->readurb); if (!(usblp->buf = kmalloc(2 * USBLP_BUF_SIZE, GFP_KERNEL))) {
kfree(usblp); err("out of memory for buf");
kfree(buf); goto abort;
return NULL;
} }
FILL_BULK_URB(usblp->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress), /* Lookup quirks for this printer. */
buf, 0, usblp_bulk_write, usblp); usblp->quirks = usblp_quirks(
dev->descriptor.idVendor,
dev->descriptor.idProduct);
/* Analyze and pick initial alternate settings and endpoints. */
protocol = usblp_select_alts(usblp);
if (protocol < 0) {
dbg("incompatible printer-class device 0x%4.4X/0x%4.4X",
dev->descriptor.idVendor,
dev->descriptor.idProduct);
goto abort;
}
if (bidir) /* Setup the selected alternate setting and endpoints. */
FILL_BULK_URB(usblp->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress), if (usblp_set_protocol(usblp, protocol) < 0)
buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE, usblp_bulk_read, usblp); goto abort;
/* Get the device_id string if possible. FIXME: Could make this kmalloc(length). */ /* Retrieve and store the device ID string. */
err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1); usblp_cache_device_id_string(usblp);
if (err >= 0) {
length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1]; /* big-endian */
if (length < DEVICE_ID_SIZE)
usblp->device_id_string[length] = '\0';
else
usblp->device_id_string[DEVICE_ID_SIZE - 1] = '\0';
dbg ("usblp%d Device ID string [%d]=%s",
minor, length, &usblp->device_id_string[2]);
}
else {
err ("usblp%d: error = %d reading IEEE-1284 Device ID string",
minor, err);
usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
}
#ifdef DEBUG #ifdef DEBUG
usblp_check_status(usblp, 0); usblp_check_status(usblp, 0);
#endif #endif
sprintf(name, "lp%d", minor); /* If we have devfs, create with perms=660. */
sprintf(name, "lp%d", usblp->minor);
/* if we have devfs, create with perms=660 */
usblp->devfs = devfs_register(usb_devfs_handle, name, usblp->devfs = devfs_register(usb_devfs_handle, name,
DEVFS_FL_DEFAULT, USB_MAJOR, DEVFS_FL_DEFAULT, USB_MAJOR,
USBLP_MINOR_BASE + minor, USBLP_MINOR_BASE + usblp->minor,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
S_IWGRP, &usblp_fops, NULL); S_IWGRP, &usblp_fops, NULL);
info("usblp%d: USB %sdirectional printer dev %d if %d alt %d", info("usblp%d: USB %sdirectional printer dev %d "
minor, bidir ? "Bi" : "Uni", dev->devnum, ifnum, alts); "if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum, ifnum,
usblp->protocol[usblp->current_protocol].alt_setting,
usblp->current_protocol, usblp->dev->descriptor.idVendor,
usblp->dev->descriptor.idProduct);
return usblp_table[usblp->minor] = usblp;
abort:
if (usblp) {
usb_free_urb(usblp->writeurb);
usb_free_urb(usblp->readurb);
if (usblp->buf) kfree(usblp->buf);
if (usblp->device_id_string) kfree(usblp->device_id_string);
kfree(usblp);
}
return NULL;
}
/*
* We are a "new" style driver with usb_device_id table,
* but our requirements are too intricate for simple match to handle.
*
* The "proto_bias" option may be used to specify the preferred protocol
* for all USB printers (1=7/1/1, 2=7/1/2, 3=7/1/3). If the device
* supports the preferred protocol, then we bind to it.
*
* The best interface for us is 7/1/2, because it is compatible
* with a stream of characters. If we find it, we bind to it.
*
* Note that the people from hpoj.sourceforge.net need to be able to
* bind to 7/1/3 (MLC/1284.4), so we provide them ioctls for this purpose.
*
* Failing 7/1/2, we look for 7/1/3, even though it's probably not
* stream-compatible, because this matches the behaviour of the old code.
*
* If nothing else, we bind to 7/1/1 - the unidirectional interface.
*/
static int usblp_select_alts(struct usblp *usblp)
{
struct usb_interface *if_alt;
struct usb_interface_descriptor *ifd;
struct usb_endpoint_descriptor *epd, *epwrite, *epread;
int p, i, e;
if_alt = &usblp->dev->actconfig->interface[usblp->ifnum];
for (p = 0; p < USBLP_MAX_PROTOCOLS; p++)
usblp->protocol[p].alt_setting = -1;
return usblp_table[minor] = usblp; /* Find out what we have. */
for (i = 0; i < if_alt->num_altsetting; i++) {
ifd = &if_alt->altsetting[i];
if (ifd->bInterfaceClass != 7 || ifd->bInterfaceSubClass != 1)
continue;
if (ifd->bInterfaceProtocol < USBLP_FIRST_PROTOCOL ||
ifd->bInterfaceProtocol > USBLP_LAST_PROTOCOL)
continue;
/* Look for bulk OUT and IN endpoints. */
epwrite = epread = 0;
for (e = 0; e < ifd->bNumEndpoints; e++) {
epd = &ifd->endpoint[e];
if ((epd->bmAttributes&USB_ENDPOINT_XFERTYPE_MASK)!=
USB_ENDPOINT_XFER_BULK)
continue;
if (!(epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK)) {
if (!epwrite) epwrite=epd;
} else {
if (!epread) epread=epd;
}
}
/* Ignore buggy hardware without the right endpoints. */
if (!epwrite || (ifd->bInterfaceProtocol > 1 && !epread))
continue;
/* Turn off reads for 7/1/1 (unidirectional) interfaces
* and buggy bidirectional printers. */
if (ifd->bInterfaceProtocol == 1) {
epread = NULL;
} else if (usblp->quirks & USBLP_QUIRK_BIDIR) {
info("Disabling reads from problem bidirectional "
"printer on usblp%d", usblp->minor);
epread = NULL;
}
usblp->protocol[ifd->bInterfaceProtocol].alt_setting = i;
usblp->protocol[ifd->bInterfaceProtocol].epwrite = epwrite;
usblp->protocol[ifd->bInterfaceProtocol].epread = epread;
}
/* If our requested protocol is supported, then use it. */
if (proto_bias >= USBLP_FIRST_PROTOCOL &&
proto_bias <= USBLP_LAST_PROTOCOL &&
usblp->protocol[proto_bias].alt_setting != -1)
return proto_bias;
/* Ordering is important here. */
if (usblp->protocol[2].alt_setting != -1) return 2;
if (usblp->protocol[1].alt_setting != -1) return 1;
if (usblp->protocol[3].alt_setting != -1) return 3;
/* If nothing is available, then don't bind to this device. */
return -1;
}
static int usblp_set_protocol(struct usblp *usblp, int protocol)
{
int r, alts;
if (protocol < USBLP_FIRST_PROTOCOL || protocol > USBLP_LAST_PROTOCOL)
return -EINVAL;
alts = usblp->protocol[protocol].alt_setting;
if (alts < 0) return -EINVAL;
r = usb_set_interface(usblp->dev, usblp->ifnum, alts);
if (r < 0) {
err("can't set desired altsetting %d on interface %d",
alts, usblp->ifnum);
return r;
}
FILL_BULK_URB(usblp->writeurb, usblp->dev,
usb_sndbulkpipe(usblp->dev,
usblp->protocol[protocol].epwrite->bEndpointAddress),
usblp->buf, 0,
usblp_bulk_write, usblp);
usblp->bidir = (usblp->protocol[protocol].epread != 0);
if (usblp->bidir)
FILL_BULK_URB(usblp->readurb, usblp->dev,
usb_rcvbulkpipe(usblp->dev,
usblp->protocol[protocol].epread->bEndpointAddress),
usblp->buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE,
usblp_bulk_read, usblp);
usblp->current_protocol = protocol;
dbg("usblp%d set protocol %d", usblp->minor, protocol);
return 0;
}
/* Retrieves and caches device ID string.
* Returns length, including length bytes but not null terminator.
* On error, returns a negative errno value. */
static int usblp_cache_device_id_string(struct usblp *usblp)
{
int err, length;
err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
if (err < 0) {
dbg("usblp%d: error = %d reading IEEE-1284 Device ID string",
usblp->minor, err);
usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
return -EIO;
}
/* First two bytes are length in big-endian.
* They count themselves, and we copy them into
* the user's buffer. */
length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1];
if (length < 2)
length = 2;
else if (length >= DEVICE_ID_SIZE)
length = DEVICE_ID_SIZE - 1;
usblp->device_id_string[length] = '\0';
dbg("usblp%d Device ID string [len=%d]=\"%s\"",
usblp->minor, length, &usblp->device_id_string[2]);
return length;
} }
static void usblp_disconnect(struct usb_device *dev, void *ptr) static void usblp_disconnect(struct usb_device *dev, void *ptr)
...@@ -757,9 +1055,7 @@ static void usblp_disconnect(struct usb_device *dev, void *ptr) ...@@ -757,9 +1055,7 @@ static void usblp_disconnect(struct usb_device *dev, void *ptr)
lock_kernel(); lock_kernel();
usblp->dev = NULL; usblp->dev = NULL;
usb_unlink_urb(usblp->writeurb); usblp_unlink_urbs(usblp);
if (usblp->bidir)
usb_unlink_urb(usblp->readurb);
if (!usblp->used) if (!usblp->used)
usblp_cleanup (usblp); usblp_cleanup (usblp);
...@@ -794,7 +1090,7 @@ static int __init usblp_init(void) ...@@ -794,7 +1090,7 @@ static int __init usblp_init(void)
{ {
if (usb_register(&usblp_driver)) if (usb_register(&usblp_driver))
return -1; return -1;
info(DRIVER_VERSION ":" DRIVER_DESC); info(DRIVER_VERSION ": " DRIVER_DESC);
return 0; return 0;
} }
...@@ -808,5 +1104,6 @@ module_exit(usblp_exit); ...@@ -808,5 +1104,6 @@ module_exit(usblp_exit);
MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC ); MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_PARM(proto_bias, "i");
MODULE_PARM_DESC(proto_bias, "Favourite protocol number");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -262,7 +262,7 @@ static int cyberjack_write (struct usb_serial_port *port, int from_user, const u ...@@ -262,7 +262,7 @@ static int cyberjack_write (struct usb_serial_port *port, int from_user, const u
port); port);
/* send the data out the bulk port */ /* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_KERNEL); result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) { if (result) {
err(__FUNCTION__ " - failed submitting write urb, error %d", result); err(__FUNCTION__ " - failed submitting write urb, error %d", result);
/* Throw away data. No better idea what to do with it. */ /* Throw away data. No better idea what to do with it. */
...@@ -331,7 +331,7 @@ static void cyberjack_read_int_callback( struct urb *urb ) ...@@ -331,7 +331,7 @@ static void cyberjack_read_int_callback( struct urb *urb )
if( !old_rdtodo ) { if( !old_rdtodo ) {
port->read_urb->dev = port->serial->dev; port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_KERNEL); result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if( result ) if( result )
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result); err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
dbg(__FUNCTION__ " - usb_submit_urb(read urb)"); dbg(__FUNCTION__ " - usb_submit_urb(read urb)");
...@@ -387,7 +387,7 @@ static void cyberjack_read_bulk_callback (struct urb *urb) ...@@ -387,7 +387,7 @@ static void cyberjack_read_bulk_callback (struct urb *urb)
/* Continue to read if we have still urbs to do. */ /* Continue to read if we have still urbs to do. */
if( priv->rdtodo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/ ) { if( priv->rdtodo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/ ) {
port->read_urb->dev = port->serial->dev; port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_KERNEL); result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result) if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result); err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
dbg(__FUNCTION__ " - usb_submit_urb(read urb)"); dbg(__FUNCTION__ " - usb_submit_urb(read urb)");
...@@ -440,7 +440,7 @@ static void cyberjack_write_bulk_callback (struct urb *urb) ...@@ -440,7 +440,7 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
port); port);
/* send the data out the bulk port */ /* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_KERNEL); result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) { if (result) {
err(__FUNCTION__ " - failed submitting write urb, error %d", result); err(__FUNCTION__ " - failed submitting write urb, error %d", result);
/* Throw away data. No better idea what to do with it. */ /* Throw away data. No better idea what to do with it. */
......
...@@ -676,7 +676,7 @@ dbg( "digi_write_oob_command: TOP: port=%d, count=%d", oob_priv->dp_port_num, co ...@@ -676,7 +676,7 @@ dbg( "digi_write_oob_command: TOP: port=%d, count=%d", oob_priv->dp_port_num, co
oob_port->write_urb->transfer_buffer_length = len; oob_port->write_urb->transfer_buffer_length = len;
oob_port->write_urb->dev = port->serial->dev; oob_port->write_urb->dev = port->serial->dev;
if( (ret=usb_submit_urb(oob_port->write_urb, GFP_KERNEL)) == 0 ) { if( (ret=usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0 ) {
oob_priv->dp_write_urb_in_use = 1; oob_priv->dp_write_urb_in_use = 1;
count -= len; count -= len;
buf += len; buf += len;
...@@ -764,7 +764,7 @@ count ); ...@@ -764,7 +764,7 @@ count );
} }
port->write_urb->dev = port->serial->dev; port->write_urb->dev = port->serial->dev;
if( (ret=usb_submit_urb(port->write_urb, GFP_KERNEL)) == 0 ) { if( (ret=usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0 ) {
priv->dp_write_urb_in_use = 1; priv->dp_write_urb_in_use = 1;
priv->dp_out_buf_len = 0; priv->dp_out_buf_len = 0;
count -= len; count -= len;
...@@ -841,7 +841,7 @@ port_priv->dp_port_num, modem_signals ); ...@@ -841,7 +841,7 @@ port_priv->dp_port_num, modem_signals );
oob_port->write_urb->transfer_buffer_length = 8; oob_port->write_urb->transfer_buffer_length = 8;
oob_port->write_urb->dev = port->serial->dev; oob_port->write_urb->dev = port->serial->dev;
if( (ret=usb_submit_urb(oob_port->write_urb, GFP_KERNEL)) == 0 ) { if( (ret=usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0 ) {
oob_priv->dp_write_urb_in_use = 1; oob_priv->dp_write_urb_in_use = 1;
port_priv->dp_modem_signals = port_priv->dp_modem_signals =
(port_priv->dp_modem_signals&~(TIOCM_DTR|TIOCM_RTS)) (port_priv->dp_modem_signals&~(TIOCM_DTR|TIOCM_RTS))
...@@ -962,7 +962,7 @@ dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num ); ...@@ -962,7 +962,7 @@ dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num );
/* restart read chain */ /* restart read chain */
if( priv->dp_throttle_restart ) { if( priv->dp_throttle_restart ) {
port->read_urb->dev = port->serial->dev; port->read_urb->dev = port->serial->dev;
ret = usb_submit_urb( port->read_urb, GFP_KERNEL ); ret = usb_submit_urb( port->read_urb, GFP_ATOMIC );
} }
/* turn throttle off */ /* turn throttle off */
...@@ -1323,7 +1323,7 @@ priv->dp_port_num, count, from_user, in_interrupt() ); ...@@ -1323,7 +1323,7 @@ priv->dp_port_num, count, from_user, in_interrupt() );
/* copy in new data */ /* copy in new data */
memcpy( data, from_user ? user_buf : buf, new_len ); memcpy( data, from_user ? user_buf : buf, new_len );
if( (ret=usb_submit_urb(port->write_urb, GFP_KERNEL)) == 0 ) { if( (ret=usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0 ) {
priv->dp_write_urb_in_use = 1; priv->dp_write_urb_in_use = 1;
ret = new_len; ret = new_len;
priv->dp_out_buf_len = 0; priv->dp_out_buf_len = 0;
...@@ -1399,7 +1399,7 @@ dbg( "digi_write_bulk_callback: TOP, urb->status=%d", urb->status ); ...@@ -1399,7 +1399,7 @@ dbg( "digi_write_bulk_callback: TOP, urb->status=%d", urb->status );
memcpy( port->write_urb->transfer_buffer+2, priv->dp_out_buf, memcpy( port->write_urb->transfer_buffer+2, priv->dp_out_buf,
priv->dp_out_buf_len ); priv->dp_out_buf_len );
if( (ret=usb_submit_urb(port->write_urb, GFP_KERNEL)) == 0 ) { if( (ret=usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0 ) {
priv->dp_write_urb_in_use = 1; priv->dp_write_urb_in_use = 1;
priv->dp_out_buf_len = 0; priv->dp_out_buf_len = 0;
} }
...@@ -1837,7 +1837,7 @@ dbg( "digi_read_bulk_callback: TOP" ); ...@@ -1837,7 +1837,7 @@ dbg( "digi_read_bulk_callback: TOP" );
/* continue read */ /* continue read */
urb->dev = port->serial->dev; urb->dev = port->serial->dev;
if( (ret=usb_submit_urb(urb, GFP_KERNEL)) != 0 ) { if( (ret=usb_submit_urb(urb, GFP_ATOMIC)) != 0 ) {
err( __FUNCTION__ ": failed resubmitting urb, ret=%d, port=%d", err( __FUNCTION__ ": failed resubmitting urb, ret=%d, port=%d",
ret, priv->dp_port_num ); ret, priv->dp_port_num );
} }
......
...@@ -256,7 +256,7 @@ static int empeg_write (struct usb_serial_port *port, int from_user, const unsig ...@@ -256,7 +256,7 @@ static int empeg_write (struct usb_serial_port *port, int from_user, const unsig
} }
if (urb->transfer_buffer == NULL) { if (urb->transfer_buffer == NULL) {
urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
if (urb->transfer_buffer == NULL) { if (urb->transfer_buffer == NULL) {
err(__FUNCTION__" no more kernel memory..."); err(__FUNCTION__" no more kernel memory...");
goto exit; goto exit;
...@@ -288,7 +288,7 @@ static int empeg_write (struct usb_serial_port *port, int from_user, const unsig ...@@ -288,7 +288,7 @@ static int empeg_write (struct usb_serial_port *port, int from_user, const unsig
urb->transfer_flags |= USB_QUEUE_BULK; urb->transfer_flags |= USB_QUEUE_BULK;
/* send it down the pipe */ /* send it down the pipe */
status = usb_submit_urb(urb, GFP_KERNEL); status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) { if (status) {
err(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status); err(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status);
bytes_sent = status; bytes_sent = status;
...@@ -441,7 +441,7 @@ static void empeg_read_bulk_callback (struct urb *urb) ...@@ -441,7 +441,7 @@ static void empeg_read_bulk_callback (struct urb *urb)
port->read_urb->transfer_flags |= USB_QUEUE_BULK; port->read_urb->transfer_flags |= USB_QUEUE_BULK;
result = usb_submit_urb(port->read_urb, GFP_KERNEL); result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result) if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result); err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
...@@ -466,7 +466,7 @@ static void empeg_unthrottle (struct usb_serial_port *port) ...@@ -466,7 +466,7 @@ static void empeg_unthrottle (struct usb_serial_port *port)
port->read_urb->dev = port->serial->dev; port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_KERNEL); result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result) if (result)
err(__FUNCTION__ " - failed submitting read urb, error %d", result); err(__FUNCTION__ " - failed submitting read urb, error %d", result);
......
...@@ -469,7 +469,7 @@ static int ftdi_sio_write (struct usb_serial_port *port, int from_user, ...@@ -469,7 +469,7 @@ static int ftdi_sio_write (struct usb_serial_port *port, int from_user,
port->write_urb->transfer_buffer, count, port->write_urb->transfer_buffer, count,
ftdi_sio_write_bulk_callback, port); ftdi_sio_write_bulk_callback, port);
result = usb_submit_urb(port->write_urb, GFP_KERNEL); result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) { if (result) {
err(__FUNCTION__ " - failed submitting write urb, error %d", result); err(__FUNCTION__ " - failed submitting write urb, error %d", result);
return 0; return 0;
...@@ -631,7 +631,7 @@ static void ftdi_sio_read_bulk_callback (struct urb *urb) ...@@ -631,7 +631,7 @@ static void ftdi_sio_read_bulk_callback (struct urb *urb)
port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
ftdi_sio_read_bulk_callback, port); ftdi_sio_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL); result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result) if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result); err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
......
...@@ -790,7 +790,7 @@ static void edge_interrupt_callback (struct urb *urb) ...@@ -790,7 +790,7 @@ static void edge_interrupt_callback (struct urb *urb)
/* we have pending bytes on the bulk in pipe, send a request */ /* we have pending bytes on the bulk in pipe, send a request */
edge_serial->read_urb->dev = edge_serial->serial->dev; edge_serial->read_urb->dev = edge_serial->serial->dev;
result = usb_submit_urb(edge_serial->read_urb, GFP_KERNEL); result = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
if (result) { if (result) {
dbg(__FUNCTION__" - usb_submit_urb(read bulk) failed with result = %d", result); dbg(__FUNCTION__" - usb_submit_urb(read bulk) failed with result = %d", result);
} }
...@@ -867,7 +867,7 @@ static void edge_bulk_in_callback (struct urb *urb) ...@@ -867,7 +867,7 @@ static void edge_bulk_in_callback (struct urb *urb)
/* there is, so resubmit our urb */ /* there is, so resubmit our urb */
edge_serial->read_urb->dev = edge_serial->serial->dev; edge_serial->read_urb->dev = edge_serial->serial->dev;
status = usb_submit_urb(edge_serial->read_urb, GFP_KERNEL); status = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
if (status) { if (status) {
err(__FUNCTION__" - usb_submit_urb(read bulk) failed, status = %d", status); err(__FUNCTION__" - usb_submit_urb(read bulk) failed, status = %d", status);
} }
...@@ -1435,7 +1435,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge ...@@ -1435,7 +1435,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
/* build the data header for the buffer and port that we are about to send out */ /* build the data header for the buffer and port that we are about to send out */
count = fifo->count; count = fifo->count;
buffer = kmalloc (count+2, GFP_KERNEL); buffer = kmalloc (count+2, GFP_ATOMIC);
if (buffer == NULL) { if (buffer == NULL) {
err(__FUNCTION__" - no more kernel memory..."); err(__FUNCTION__" - no more kernel memory...");
edge_port->write_in_progress = FALSE; edge_port->write_in_progress = FALSE;
...@@ -1474,7 +1474,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge ...@@ -1474,7 +1474,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
urb->transfer_flags |= USB_QUEUE_BULK; urb->transfer_flags |= USB_QUEUE_BULK;
urb->dev = edge_serial->serial->dev; urb->dev = edge_serial->serial->dev;
status = usb_submit_urb(urb, GFP_KERNEL); status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) { if (status) {
/* something went wrong */ /* something went wrong */
dbg(__FUNCTION__" - usb_submit_urb(write bulk) failed"); dbg(__FUNCTION__" - usb_submit_urb(write bulk) failed");
...@@ -2431,7 +2431,7 @@ static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u ...@@ -2431,7 +2431,7 @@ static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u
dbg(__FUNCTION__" - %d, %d", command, param); dbg(__FUNCTION__" - %d, %d", command, param);
buffer = kmalloc (10, GFP_KERNEL); buffer = kmalloc (10, GFP_ATOMIC);
if (!buffer) { if (!buffer) {
err(__FUNCTION__" - kmalloc(%d) failed.\n", 10); err(__FUNCTION__" - kmalloc(%d) failed.\n", 10);
return -ENOMEM; return -ENOMEM;
...@@ -2467,7 +2467,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer ...@@ -2467,7 +2467,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
usb_serial_debug_data (__FILE__, __FUNCTION__, length, buffer); usb_serial_debug_data (__FILE__, __FUNCTION__, length, buffer);
/* Allocate our next urb */ /* Allocate our next urb */
urb = usb_alloc_urb (0, GFP_KERNEL); urb = usb_alloc_urb (0, GFP_ATOMIC);
if (!urb) if (!urb)
return -ENOMEM; return -ENOMEM;
...@@ -2482,7 +2482,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer ...@@ -2482,7 +2482,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
urb->transfer_flags |= USB_QUEUE_BULK; urb->transfer_flags |= USB_QUEUE_BULK;
edge_port->commandPending = TRUE; edge_port->commandPending = TRUE;
status = usb_submit_urb(urb, GFP_KERNEL); status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) { if (status) {
/* something went wrong */ /* something went wrong */
...@@ -2532,7 +2532,7 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa ...@@ -2532,7 +2532,7 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa
} }
// Alloc memory for the string of commands. // Alloc memory for the string of commands.
cmdBuffer = kmalloc (0x100, GFP_KERNEL); cmdBuffer = kmalloc (0x100, GFP_ATOMIC);
if (!cmdBuffer) { if (!cmdBuffer) {
err(__FUNCTION__" - kmalloc(%d) failed.\n", 0x100); err(__FUNCTION__" - kmalloc(%d) failed.\n", 0x100);
return -ENOMEM; return -ENOMEM;
...@@ -2618,7 +2618,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r ...@@ -2618,7 +2618,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
dbg (__FUNCTION__" - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", regValue); dbg (__FUNCTION__" - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", regValue);
// Alloc memory for the string of commands. // Alloc memory for the string of commands.
cmdBuffer = kmalloc (0x10, GFP_KERNEL); cmdBuffer = kmalloc (0x10, GFP_ATOMIC);
if (cmdBuffer == NULL ) { if (cmdBuffer == NULL ) {
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -297,7 +297,7 @@ static void ipaq_read_bulk_callback(struct urb *urb) ...@@ -297,7 +297,7 @@ static void ipaq_read_bulk_callback(struct urb *urb)
usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
ipaq_read_bulk_callback, port); ipaq_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL); result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result) if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result); err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
return; return;
...@@ -412,7 +412,7 @@ static int ipaq_write_flush(struct usb_serial_port *port) ...@@ -412,7 +412,7 @@ static int ipaq_write_flush(struct usb_serial_port *port)
usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
port->write_urb->transfer_buffer, count, ipaq_write_bulk_callback, port->write_urb->transfer_buffer, count, ipaq_write_bulk_callback,
port); port);
result = usb_submit_urb(urb, GFP_KERNEL); result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) { if (result) {
err(__FUNCTION__ " - failed submitting write urb, error %d", result); err(__FUNCTION__ " - failed submitting write urb, error %d", result);
} }
......
...@@ -405,7 +405,7 @@ static int ir_write (struct usb_serial_port *port, int from_user, const unsigned ...@@ -405,7 +405,7 @@ static int ir_write (struct usb_serial_port *port, int from_user, const unsigned
= USB_QUEUE_BULK = USB_QUEUE_BULK
| USB_ZERO_PACKET; | USB_ZERO_PACKET;
result = usb_submit_urb (port->write_urb, GFP_KERNEL); result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
if (result) if (result)
err("%s - failed submitting write urb, error %d", __FUNCTION__, result); err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
else else
...@@ -515,7 +515,7 @@ static void ir_read_bulk_callback (struct urb *urb) ...@@ -515,7 +515,7 @@ static void ir_read_bulk_callback (struct urb *urb)
port->read_urb->transfer_flags = USB_QUEUE_BULK; port->read_urb->transfer_flags = USB_QUEUE_BULK;
result = usb_submit_urb(port->read_urb, GFP_KERNEL); result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result) if (result)
err("%s - failed resubmitting read urb, error %d", err("%s - failed resubmitting read urb, error %d",
......
...@@ -378,7 +378,7 @@ static int keyspan_write(struct usb_serial_port *port, int from_user, ...@@ -378,7 +378,7 @@ static int keyspan_write(struct usb_serial_port *port, int from_user,
this_urb->transfer_flags &= ~USB_ASYNC_UNLINK; this_urb->transfer_flags &= ~USB_ASYNC_UNLINK;
this_urb->dev = port->serial->dev; this_urb->dev = port->serial->dev;
if ((err = usb_submit_urb(this_urb, GFP_KERNEL)) != 0) { if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
dbg("usb_submit_urb(write bulk) failed (%d)\n", err); dbg("usb_submit_urb(write bulk) failed (%d)\n", err);
} }
p_priv->tx_start_time[flip] = jiffies; p_priv->tx_start_time[flip] = jiffies;
...@@ -436,7 +436,7 @@ static void usa26_indat_callback(struct urb *urb) ...@@ -436,7 +436,7 @@ static void usa26_indat_callback(struct urb *urb)
/* Resubmit urb so we continue receiving */ /* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev; urb->dev = port->serial->dev;
if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) { if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err); dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
} }
return; return;
...@@ -535,7 +535,7 @@ static void usa26_instat_callback(struct urb *urb) ...@@ -535,7 +535,7 @@ static void usa26_instat_callback(struct urb *urb)
exit: exit:
/* Resubmit urb so we continue receiving */ /* Resubmit urb so we continue receiving */
urb->dev = serial->dev; urb->dev = serial->dev;
if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) { if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err); dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
} }
} }
...@@ -586,7 +586,7 @@ static void usa28_indat_callback(struct urb *urb) ...@@ -586,7 +586,7 @@ static void usa28_indat_callback(struct urb *urb)
/* Resubmit urb so we continue receiving */ /* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev; urb->dev = port->serial->dev;
if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) { if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n",
err); err);
} }
...@@ -671,7 +671,7 @@ static void usa28_instat_callback(struct urb *urb) ...@@ -671,7 +671,7 @@ static void usa28_instat_callback(struct urb *urb)
exit: exit:
/* Resubmit urb so we continue receiving */ /* Resubmit urb so we continue receiving */
urb->dev = serial->dev; urb->dev = serial->dev;
if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) { if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err); dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
} }
} }
...@@ -764,7 +764,7 @@ static void usa49_instat_callback(struct urb *urb) ...@@ -764,7 +764,7 @@ static void usa49_instat_callback(struct urb *urb)
/* Resubmit urb so we continue receiving */ /* Resubmit urb so we continue receiving */
urb->dev = serial->dev; urb->dev = serial->dev;
if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) { if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err); dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
} }
} }
...@@ -819,7 +819,7 @@ static void usa49_indat_callback(struct urb *urb) ...@@ -819,7 +819,7 @@ static void usa49_indat_callback(struct urb *urb)
/* Resubmit urb so we continue receiving */ /* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev; urb->dev = port->serial->dev;
if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) { if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err); dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
} }
} }
......
...@@ -292,7 +292,7 @@ static void keyspan_pda_rx_unthrottle (struct usb_serial_port *port) ...@@ -292,7 +292,7 @@ static void keyspan_pda_rx_unthrottle (struct usb_serial_port *port)
/* just restart the receive interrupt URB */ /* just restart the receive interrupt URB */
dbg("keyspan_pda_rx_unthrottle port %d", port->number); dbg("keyspan_pda_rx_unthrottle port %d", port->number);
port->interrupt_in_urb->dev = port->serial->dev; port->interrupt_in_urb->dev = port->serial->dev;
if (usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL)) if (usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC))
dbg(" usb_submit_urb(read urb) failed"); dbg(" usb_submit_urb(read urb) failed");
return; return;
} }
...@@ -584,7 +584,7 @@ static int keyspan_pda_write(struct usb_serial_port *port, int from_user, ...@@ -584,7 +584,7 @@ static int keyspan_pda_write(struct usb_serial_port *port, int from_user,
priv->tx_room -= count; priv->tx_room -= count;
port->write_urb->dev = port->serial->dev; port->write_urb->dev = port->serial->dev;
rc = usb_submit_urb(port->write_urb, GFP_KERNEL); rc = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (rc) { if (rc) {
dbg(" usb_submit_urb(write bulk) failed"); dbg(" usb_submit_urb(write bulk) failed");
goto exit; goto exit;
......
...@@ -519,7 +519,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user, ...@@ -519,7 +519,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user,
} }
if (urb->transfer_buffer == NULL) { if (urb->transfer_buffer == NULL) {
urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
if (urb->transfer_buffer == NULL) { if (urb->transfer_buffer == NULL) {
err(__FUNCTION__ " - no more kernel memory..."); err(__FUNCTION__ " - no more kernel memory...");
goto exit; goto exit;
...@@ -555,7 +555,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user, ...@@ -555,7 +555,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user,
/* send the data out the bulk port */ /* send the data out the bulk port */
result = usb_submit_urb(urb, GFP_KERNEL); result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) { if (result) {
err(__FUNCTION__ err(__FUNCTION__
" - failed submitting write urb, error %d", result); " - failed submitting write urb, error %d", result);
...@@ -721,7 +721,7 @@ static void klsi_105_read_bulk_callback (struct urb *urb) ...@@ -721,7 +721,7 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
port->read_urb->transfer_buffer_length, port->read_urb->transfer_buffer_length,
klsi_105_read_bulk_callback, klsi_105_read_bulk_callback,
port); port);
rc = usb_submit_urb(port->read_urb, GFP_KERNEL); rc = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (rc) if (rc)
err(__FUNCTION__ err(__FUNCTION__
" - failed resubmitting read urb, error %d", rc); " - failed resubmitting read urb, error %d", rc);
...@@ -1019,7 +1019,7 @@ static void klsi_105_unthrottle (struct usb_serial_port *port) ...@@ -1019,7 +1019,7 @@ static void klsi_105_unthrottle (struct usb_serial_port *port)
dbg(__FUNCTION__ " - port %d", port->number); dbg(__FUNCTION__ " - port %d", port->number);
port->read_urb->dev = port->serial->dev; port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_KERNEL); result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result) if (result)
err(__FUNCTION__ " - failed submitting read urb, error %d", err(__FUNCTION__ " - failed submitting read urb, error %d",
result); result);
......
...@@ -470,7 +470,7 @@ static int mct_u232_write (struct usb_serial_port *port, int from_user, ...@@ -470,7 +470,7 @@ static int mct_u232_write (struct usb_serial_port *port, int from_user,
port); port);
/* send the data out the bulk port */ /* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_KERNEL); result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) { if (result) {
err(__FUNCTION__ err(__FUNCTION__
" - failed submitting write urb, error %d", result); " - failed submitting write urb, error %d", result);
......
...@@ -265,7 +265,7 @@ static void omninet_read_bulk_callback (struct urb *urb) ...@@ -265,7 +265,7 @@ static void omninet_read_bulk_callback (struct urb *urb)
usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
urb->transfer_buffer, urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_buffer_length,
omninet_read_bulk_callback, port); omninet_read_bulk_callback, port);
result = usb_submit_urb(urb, GFP_KERNEL); result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result); err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
...@@ -316,7 +316,7 @@ static int omninet_write (struct usb_serial_port *port, int from_user, const uns ...@@ -316,7 +316,7 @@ static int omninet_write (struct usb_serial_port *port, int from_user, const uns
wport->write_urb->transfer_buffer_length = 64; wport->write_urb->transfer_buffer_length = 64;
wport->write_urb->dev = serial->dev; wport->write_urb->dev = serial->dev;
result = usb_submit_urb(wport->write_urb, GFP_KERNEL); result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);
if (result) if (result)
err(__FUNCTION__ " - failed submitting write urb, error %d", result); err(__FUNCTION__ " - failed submitting write urb, error %d", result);
else else
......
...@@ -195,7 +195,7 @@ static int pl2303_write (struct usb_serial_port *port, int from_user, const uns ...@@ -195,7 +195,7 @@ static int pl2303_write (struct usb_serial_port *port, int from_user, const uns
port->write_urb->transfer_buffer_length = count; port->write_urb->transfer_buffer_length = count;
port->write_urb->dev = port->serial->dev; port->write_urb->dev = port->serial->dev;
result = usb_submit_urb (port->write_urb, GFP_KERNEL); result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
if (result) if (result)
err(__FUNCTION__ " - failed submitting write urb, error %d", result); err(__FUNCTION__ " - failed submitting write urb, error %d", result);
else else
...@@ -643,7 +643,7 @@ static void pl2303_read_bulk_callback (struct urb *urb) ...@@ -643,7 +643,7 @@ static void pl2303_read_bulk_callback (struct urb *urb)
dbg (__FUNCTION__ " - caught -EPROTO, resubmitting the urb"); dbg (__FUNCTION__ " - caught -EPROTO, resubmitting the urb");
urb->status = 0; urb->status = 0;
urb->dev = serial->dev; urb->dev = serial->dev;
result = usb_submit_urb(urb, GFP_KERNEL); result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result); err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
return; return;
...@@ -668,7 +668,7 @@ static void pl2303_read_bulk_callback (struct urb *urb) ...@@ -668,7 +668,7 @@ static void pl2303_read_bulk_callback (struct urb *urb)
/* Schedule the next read _if_ we are still open */ /* Schedule the next read _if_ we are still open */
if (port->open_count) { if (port->open_count) {
urb->dev = serial->dev; urb->dev = serial->dev;
result = usb_submit_urb(urb, GFP_KERNEL); result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result); err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
} }
...@@ -697,7 +697,7 @@ static void pl2303_write_bulk_callback (struct urb *urb) ...@@ -697,7 +697,7 @@ static void pl2303_write_bulk_callback (struct urb *urb)
dbg (__FUNCTION__ " - nonzero write bulk status received: %d", urb->status); dbg (__FUNCTION__ " - nonzero write bulk status received: %d", urb->status);
port->write_urb->transfer_buffer_length = 1; port->write_urb->transfer_buffer_length = 1;
port->write_urb->dev = port->serial->dev; port->write_urb->dev = port->serial->dev;
result = usb_submit_urb (port->write_urb, GFP_KERNEL); result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
if (result) if (result)
err(__FUNCTION__ " - failed resubmitting write urb, error %d", result); err(__FUNCTION__ " - failed resubmitting write urb, error %d", result);
......
...@@ -899,7 +899,7 @@ static int generic_write (struct usb_serial_port *port, int from_user, const uns ...@@ -899,7 +899,7 @@ static int generic_write (struct usb_serial_port *port, int from_user, const uns
generic_write_bulk_callback), port); generic_write_bulk_callback), port);
/* send the data out the bulk port */ /* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_KERNEL); result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) if (result)
err(__FUNCTION__ " - failed submitting write urb, error %d", result); err(__FUNCTION__ " - failed submitting write urb, error %d", result);
else else
...@@ -989,7 +989,7 @@ static void generic_read_bulk_callback (struct urb *urb) ...@@ -989,7 +989,7 @@ static void generic_read_bulk_callback (struct urb *urb)
((serial->type->read_bulk_callback) ? ((serial->type->read_bulk_callback) ?
serial->type->read_bulk_callback : serial->type->read_bulk_callback :
generic_read_bulk_callback), port); generic_read_bulk_callback), port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL); result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result) if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result); err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
} }
......
...@@ -344,13 +344,13 @@ static int visor_write (struct usb_serial_port *port, int from_user, const unsig ...@@ -344,13 +344,13 @@ static int visor_write (struct usb_serial_port *port, int from_user, const unsig
dbg(__FUNCTION__ " - port %d", port->number); dbg(__FUNCTION__ " - port %d", port->number);
buffer = kmalloc (count, GFP_KERNEL); buffer = kmalloc (count, GFP_ATOMIC);
if (!buffer) { if (!buffer) {
err ("out of memory"); err ("out of memory");
return -ENOMEM; return -ENOMEM;
} }
urb = usb_alloc_urb(0, GFP_KERNEL); urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) { if (!urb) {
err ("no more free urbs"); err ("no more free urbs");
kfree (buffer); kfree (buffer);
...@@ -377,7 +377,7 @@ static int visor_write (struct usb_serial_port *port, int from_user, const unsig ...@@ -377,7 +377,7 @@ static int visor_write (struct usb_serial_port *port, int from_user, const unsig
urb->transfer_flags |= USB_QUEUE_BULK; urb->transfer_flags |= USB_QUEUE_BULK;
/* send it down the pipe */ /* send it down the pipe */
status = usb_submit_urb(urb, GFP_KERNEL); status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) { if (status) {
err(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status); err(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status);
count = status; count = status;
...@@ -491,7 +491,7 @@ static void visor_read_bulk_callback (struct urb *urb) ...@@ -491,7 +491,7 @@ static void visor_read_bulk_callback (struct urb *urb)
port->read_urb->transfer_buffer, port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length, port->read_urb->transfer_buffer_length,
visor_read_bulk_callback, port); visor_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL); result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result) if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result); err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
return; return;
...@@ -512,7 +512,7 @@ static void visor_unthrottle (struct usb_serial_port *port) ...@@ -512,7 +512,7 @@ static void visor_unthrottle (struct usb_serial_port *port)
dbg(__FUNCTION__ " - port %d", port->number); dbg(__FUNCTION__ " - port %d", port->number);
port->read_urb->dev = port->serial->dev; port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_KERNEL); result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result) if (result)
err(__FUNCTION__ " - failed submitting read urb, error %d", result); err(__FUNCTION__ " - failed submitting read urb, error %d", result);
} }
......
...@@ -240,7 +240,7 @@ static void command_port_read_callback (struct urb *urb) ...@@ -240,7 +240,7 @@ static void command_port_read_callback (struct urb *urb)
usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
command_port_read_callback, port); command_port_read_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL); result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result) if (result)
dbg(__FUNCTION__ " - failed resubmitting read urb, error %d", result); dbg(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
} }
......
...@@ -6,7 +6,226 @@ ...@@ -6,7 +6,226 @@
* table of configured filesystems * table of configured filesystems
*/ */
#include <linux/config.h>
#include <linux/slab.h>
#include <linux/kmod.h>
#define __NO_VERSION__
#include <linux/module.h>
#include <asm/uaccess.h>
/* /*
* Code will move here from fs/super.c and yes, it will be fs type handling * Handling of filesystem drivers list.
* stuff. * Rules:
* Inclusion to/removals from/scanning of list are protected by spinlock.
* During the unload module must call unregister_filesystem().
* We can access the fields of list element if:
* 1) spinlock is held or
* 2) we hold the reference to the module.
* The latter can be guaranteed by call of try_inc_mod_count(); if it
* returned 0 we must skip the element, otherwise we got the reference.
* Once the reference is obtained we can drop the spinlock.
*/
static struct file_system_type *file_systems;
static rwlock_t file_systems_lock = RW_LOCK_UNLOCKED;
/* WARNING: This can be used only if we _already_ own a reference */
void get_filesystem(struct file_system_type *fs)
{
if (fs->owner)
__MOD_INC_USE_COUNT(fs->owner);
}
void put_filesystem(struct file_system_type *fs)
{
if (fs->owner)
__MOD_DEC_USE_COUNT(fs->owner);
}
static struct file_system_type **find_filesystem(const char *name)
{
struct file_system_type **p;
for (p=&file_systems; *p; p=&(*p)->next)
if (strcmp((*p)->name,name) == 0)
break;
return p;
}
/**
* register_filesystem - register a new filesystem
* @fs: the file system structure
*
* Adds the file system passed to the list of file systems the kernel
* is aware of for mount and other syscalls. Returns 0 on success,
* or a negative errno code on an error.
*
* The &struct file_system_type that is passed is linked into the kernel
* structures and must not be freed until the file system has been
* unregistered.
*/ */
int register_filesystem(struct file_system_type * fs)
{
int res = 0;
struct file_system_type ** p;
if (!fs)
return -EINVAL;
if (fs->next)
return -EBUSY;
INIT_LIST_HEAD(&fs->fs_supers);
write_lock(&file_systems_lock);
p = find_filesystem(fs->name);
if (*p)
res = -EBUSY;
else
*p = fs;
write_unlock(&file_systems_lock);
return res;
}
/**
* unregister_filesystem - unregister a file system
* @fs: filesystem to unregister
*
* Remove a file system that was previously successfully registered
* with the kernel. An error is returned if the file system is not found.
* Zero is returned on a success.
*
* Once this function has returned the &struct file_system_type structure
* may be freed or reused.
*/
int unregister_filesystem(struct file_system_type * fs)
{
struct file_system_type ** tmp;
write_lock(&file_systems_lock);
tmp = &file_systems;
while (*tmp) {
if (fs == *tmp) {
*tmp = fs->next;
fs->next = NULL;
write_unlock(&file_systems_lock);
return 0;
}
tmp = &(*tmp)->next;
}
write_unlock(&file_systems_lock);
return -EINVAL;
}
static int fs_index(const char * __name)
{
struct file_system_type * tmp;
char * name;
int err, index;
name = getname(__name);
err = PTR_ERR(name);
if (IS_ERR(name))
return err;
err = -EINVAL;
read_lock(&file_systems_lock);
for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
if (strcmp(tmp->name,name) == 0) {
err = index;
break;
}
}
read_unlock(&file_systems_lock);
putname(name);
return err;
}
static int fs_name(unsigned int index, char * buf)
{
struct file_system_type * tmp;
int len, res;
read_lock(&file_systems_lock);
for (tmp = file_systems; tmp; tmp = tmp->next, index--)
if (index <= 0 && try_inc_mod_count(tmp->owner))
break;
read_unlock(&file_systems_lock);
if (!tmp)
return -EINVAL;
/* OK, we got the reference, so we can safely block */
len = strlen(tmp->name) + 1;
res = copy_to_user(buf, tmp->name, len) ? -EFAULT : 0;
put_filesystem(tmp);
return res;
}
static int fs_maxindex(void)
{
struct file_system_type * tmp;
int index;
read_lock(&file_systems_lock);
for (tmp = file_systems, index = 0 ; tmp ; tmp = tmp->next, index++)
;
read_unlock(&file_systems_lock);
return index;
}
/*
* Whee.. Weird sysv syscall.
*/
asmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2)
{
int retval = -EINVAL;
switch (option) {
case 1:
retval = fs_index((const char *) arg1);
break;
case 2:
retval = fs_name(arg1, (char *) arg2);
break;
case 3:
retval = fs_maxindex();
break;
}
return retval;
}
int get_filesystem_list(char * buf)
{
int len = 0;
struct file_system_type * tmp;
read_lock(&file_systems_lock);
tmp = file_systems;
while (tmp && len < PAGE_SIZE - 80) {
len += sprintf(buf+len, "%s\t%s\n",
(tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev",
tmp->name);
tmp = tmp->next;
}
read_unlock(&file_systems_lock);
return len;
}
struct file_system_type *get_fs_type(const char *name)
{
struct file_system_type *fs;
read_lock(&file_systems_lock);
fs = *(find_filesystem(name));
if (fs && !try_inc_mod_count(fs->owner))
fs = NULL;
read_unlock(&file_systems_lock);
if (!fs && (request_module(name) == 0)) {
read_lock(&file_systems_lock);
fs = *(find_filesystem(name));
if (fs && !try_inc_mod_count(fs->owner))
fs = NULL;
read_unlock(&file_systems_lock);
}
return fs;
}
...@@ -110,14 +110,13 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, ...@@ -110,14 +110,13 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
struct buffer_head *bh = NULL; struct buffer_head *bh = NULL;
int len; int len;
int map; int map;
int high_sierra;
int first_de = 1; int first_de = 1;
char *p = NULL; /* Quiet GCC */ char *p = NULL; /* Quiet GCC */
struct iso_directory_record *de; struct iso_directory_record *de;
struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
offset = filp->f_pos & (bufsize - 1); offset = filp->f_pos & (bufsize - 1);
block = filp->f_pos >> bufbits; block = filp->f_pos >> bufbits;
high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
while (filp->f_pos < inode->i_size) { while (filp->f_pos < inode->i_size) {
int de_len; int de_len;
...@@ -166,7 +165,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, ...@@ -166,7 +165,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
de = tmpde; de = tmpde;
} }
if (de->flags[-high_sierra] & 0x80) { if (de->flags[-sbi->s_high_sierra] & 0x80) {
first_de = 0; first_de = 0;
filp->f_pos += de_len; filp->f_pos += de_len;
continue; continue;
...@@ -194,16 +193,16 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, ...@@ -194,16 +193,16 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
/* Handle everything else. Do name translation if there /* Handle everything else. Do name translation if there
is no Rock Ridge NM field. */ is no Rock Ridge NM field. */
if (inode->i_sb->u.isofs_sb.s_unhide == 'n') { if (sbi->s_unhide == 'n') {
/* Do not report hidden or associated files */ /* Do not report hidden or associated files */
if (de->flags[-high_sierra] & 5) { if (de->flags[-sbi->s_high_sierra] & 5) {
filp->f_pos += de_len; filp->f_pos += de_len;
continue; continue;
} }
} }
map = 1; map = 1;
if (inode->i_sb->u.isofs_sb.s_rock) { if (sbi->s_rock) {
len = get_rock_ridge_filename(de, tmpname, inode); len = get_rock_ridge_filename(de, tmpname, inode);
if (len != 0) { /* may be -1 */ if (len != 0) { /* may be -1 */
p = tmpname; p = tmpname;
...@@ -212,16 +211,16 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, ...@@ -212,16 +211,16 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
} }
if (map) { if (map) {
#ifdef CONFIG_JOLIET #ifdef CONFIG_JOLIET
if (inode->i_sb->u.isofs_sb.s_joliet_level) { if (sbi->s_joliet_level) {
len = get_joliet_filename(de, tmpname, inode); len = get_joliet_filename(de, tmpname, inode);
p = tmpname; p = tmpname;
} else } else
#endif #endif
if (inode->i_sb->u.isofs_sb.s_mapping == 'a') { if (sbi->s_mapping == 'a') {
len = get_acorn_filename(de, tmpname, inode); len = get_acorn_filename(de, tmpname, inode);
p = tmpname; p = tmpname;
} else } else
if (inode->i_sb->u.isofs_sb.s_mapping == 'n') { if (sbi->s_mapping == 'n') {
len = isofs_name_translate(de, tmpname, inode); len = isofs_name_translate(de, tmpname, inode);
p = tmpname; p = tmpname;
} else { } else {
......
...@@ -60,10 +60,11 @@ static int isofs_dentry_cmp_ms(struct dentry *dentry, struct qstr *a, struct qst ...@@ -60,10 +60,11 @@ static int isofs_dentry_cmp_ms(struct dentry *dentry, struct qstr *a, struct qst
static void isofs_put_super(struct super_block *sb) static void isofs_put_super(struct super_block *sb)
{ {
struct isofs_sb_info *sbi = ISOFS_SB(sb);
#ifdef CONFIG_JOLIET #ifdef CONFIG_JOLIET
if (sb->u.isofs_sb.s_nls_iocharset) { if (sbi->s_nls_iocharset) {
unload_nls(sb->u.isofs_sb.s_nls_iocharset); unload_nls(sbi->s_nls_iocharset);
sb->u.isofs_sb.s_nls_iocharset = NULL; sbi->s_nls_iocharset = NULL;
} }
#endif #endif
...@@ -72,6 +73,8 @@ static void isofs_put_super(struct super_block *sb) ...@@ -72,6 +73,8 @@ static void isofs_put_super(struct super_block *sb)
check_malloc, check_bread); check_malloc, check_bread);
#endif #endif
kfree(sbi);
sb->u.generic_sbp = NULL;
return; return;
} }
...@@ -518,7 +521,6 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) ...@@ -518,7 +521,6 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
struct iso_supplementary_descriptor *sec = NULL; struct iso_supplementary_descriptor *sec = NULL;
struct iso_directory_record * rootp; struct iso_directory_record * rootp;
int joliet_level = 0; int joliet_level = 0;
int high_sierra;
int iso_blknum, block; int iso_blknum, block;
int orig_zonesize; int orig_zonesize;
int table; int table;
...@@ -526,9 +528,16 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) ...@@ -526,9 +528,16 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
unsigned long first_data_zone; unsigned long first_data_zone;
struct inode * inode; struct inode * inode;
struct iso9660_options opt; struct iso9660_options opt;
struct isofs_sb_info * sbi;
sbi = kmalloc(sizeof(struct isofs_sb_info), GFP_KERNEL);
if (!sbi)
return -ENOMEM;
s->u.generic_sbp = sbi;
memset(sbi, 0, sizeof(struct isofs_sb_info));
if (!parse_options((char *) data, &opt)) if (!parse_options((char *) data, &opt))
goto out_unlock; goto out_freesbi;
#if 0 #if 0
printk("map = %c\n", opt.map); printk("map = %c\n", opt.map);
...@@ -554,7 +563,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) ...@@ -554,7 +563,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
*/ */
opt.blocksize = sb_min_blocksize(s, opt.blocksize); opt.blocksize = sb_min_blocksize(s, opt.blocksize);
s->u.isofs_sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */ sbi->s_high_sierra = 0; /* default is iso9660 */
vol_desc_start = (opt.sbsector != -1) ? vol_desc_start = (opt.sbsector != -1) ?
opt.sbsector : isofs_get_last_session(s,opt.session); opt.sbsector : isofs_get_last_session(s,opt.session);
...@@ -614,8 +623,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) ...@@ -614,8 +623,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
if (isonum_711 (hdp->type) != ISO_VD_PRIMARY) if (isonum_711 (hdp->type) != ISO_VD_PRIMARY)
goto out_freebh; goto out_freebh;
s->u.isofs_sb.s_high_sierra = 1; sbi->s_high_sierra = 1;
high_sierra = 1;
opt.rock = 'n'; opt.rock = 'n';
h_pri = (struct hs_primary_descriptor *)vdp; h_pri = (struct hs_primary_descriptor *)vdp;
goto root_found; goto root_found;
...@@ -646,29 +654,29 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) ...@@ -646,29 +654,29 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
pri = (struct iso_primary_descriptor *) sec; pri = (struct iso_primary_descriptor *) sec;
} }
if(high_sierra){ if(sbi->s_high_sierra){
rootp = (struct iso_directory_record *) h_pri->root_directory_record; rootp = (struct iso_directory_record *) h_pri->root_directory_record;
#ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS #ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS
if (isonum_723 (h_pri->volume_set_size) != 1) if (isonum_723 (h_pri->volume_set_size) != 1)
goto out_no_support; goto out_no_support;
#endif /* IGNORE_WRONG_MULTI_VOLUME_SPECS */ #endif /* IGNORE_WRONG_MULTI_VOLUME_SPECS */
s->u.isofs_sb.s_nzones = isonum_733 (h_pri->volume_space_size); sbi->s_nzones = isonum_733 (h_pri->volume_space_size);
s->u.isofs_sb.s_log_zone_size = isonum_723 (h_pri->logical_block_size); sbi->s_log_zone_size = isonum_723 (h_pri->logical_block_size);
s->u.isofs_sb.s_max_size = isonum_733(h_pri->volume_space_size); sbi->s_max_size = isonum_733(h_pri->volume_space_size);
} else { } else {
rootp = (struct iso_directory_record *) pri->root_directory_record; rootp = (struct iso_directory_record *) pri->root_directory_record;
#ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS #ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS
if (isonum_723 (pri->volume_set_size) != 1) if (isonum_723 (pri->volume_set_size) != 1)
goto out_no_support; goto out_no_support;
#endif /* IGNORE_WRONG_MULTI_VOLUME_SPECS */ #endif /* IGNORE_WRONG_MULTI_VOLUME_SPECS */
s->u.isofs_sb.s_nzones = isonum_733 (pri->volume_space_size); sbi->s_nzones = isonum_733 (pri->volume_space_size);
s->u.isofs_sb.s_log_zone_size = isonum_723 (pri->logical_block_size); sbi->s_log_zone_size = isonum_723 (pri->logical_block_size);
s->u.isofs_sb.s_max_size = isonum_733(pri->volume_space_size); sbi->s_max_size = isonum_733(pri->volume_space_size);
} }
s->u.isofs_sb.s_ninodes = 0; /* No way to figure this out easily */ sbi->s_ninodes = 0; /* No way to figure this out easily */
orig_zonesize = s -> u.isofs_sb.s_log_zone_size; orig_zonesize = sbi->s_log_zone_size;
/* /*
* If the zone size is smaller than the hardware sector size, * If the zone size is smaller than the hardware sector size,
* this is a fatal error. This would occur if the disc drive * this is a fatal error. This would occur if the disc drive
...@@ -680,10 +688,10 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) ...@@ -680,10 +688,10 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
goto out_bad_size; goto out_bad_size;
/* RDE: convert log zone size to bit shift */ /* RDE: convert log zone size to bit shift */
switch (s -> u.isofs_sb.s_log_zone_size) switch (sbi->s_log_zone_size)
{ case 512: s -> u.isofs_sb.s_log_zone_size = 9; break; { case 512: sbi->s_log_zone_size = 9; break;
case 1024: s -> u.isofs_sb.s_log_zone_size = 10; break; case 1024: sbi->s_log_zone_size = 10; break;
case 2048: s -> u.isofs_sb.s_log_zone_size = 11; break; case 2048: sbi->s_log_zone_size = 11; break;
default: default:
goto out_bad_zone_size; goto out_bad_zone_size;
...@@ -705,16 +713,16 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) ...@@ -705,16 +713,16 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
first_data_zone = ((isonum_733 (rootp->extent) + first_data_zone = ((isonum_733 (rootp->extent) +
isonum_711 (rootp->ext_attr_length)) isonum_711 (rootp->ext_attr_length))
<< s -> u.isofs_sb.s_log_zone_size); << sbi->s_log_zone_size);
s->u.isofs_sb.s_firstdatazone = first_data_zone; sbi->s_firstdatazone = first_data_zone;
#ifndef BEQUIET #ifndef BEQUIET
printk(KERN_DEBUG "Max size:%ld Log zone size:%ld\n", printk(KERN_DEBUG "Max size:%ld Log zone size:%ld\n",
s->u.isofs_sb.s_max_size, sbi->s_max_size,
1UL << s->u.isofs_sb.s_log_zone_size); 1UL << sbi->s_log_zone_size);
printk(KERN_DEBUG "First datazone:%ld Root inode number:%ld\n", printk(KERN_DEBUG "First datazone:%ld Root inode number:%ld\n",
s->u.isofs_sb.s_firstdatazone >> s -> u.isofs_sb.s_log_zone_size, sbi->s_firstdatazone >> sbi->s_log_zone_size,
s->u.isofs_sb.s_firstdatazone); sbi->s_firstdatazone);
if(high_sierra) if(sbi->s_high_sierra)
printk(KERN_DEBUG "Disc in High Sierra format.\n"); printk(KERN_DEBUG "Disc in High Sierra format.\n");
#endif #endif
...@@ -732,7 +740,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) ...@@ -732,7 +740,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
pri->root_directory_record; pri->root_directory_record;
first_data_zone = ((isonum_733 (rootp->extent) + first_data_zone = ((isonum_733 (rootp->extent) +
isonum_711 (rootp->ext_attr_length)) isonum_711 (rootp->ext_attr_length))
<< s -> u.isofs_sb.s_log_zone_size); << sbi->s_log_zone_size);
} }
/* /*
...@@ -761,43 +769,43 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) ...@@ -761,43 +769,43 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
*/ */
sb_set_blocksize(s, orig_zonesize); sb_set_blocksize(s, orig_zonesize);
s->u.isofs_sb.s_nls_iocharset = NULL; sbi->s_nls_iocharset = NULL;
#ifdef CONFIG_JOLIET #ifdef CONFIG_JOLIET
if (joliet_level && opt.utf8 == 0) { if (joliet_level && opt.utf8 == 0) {
char * p = opt.iocharset ? opt.iocharset : "iso8859-1"; char * p = opt.iocharset ? opt.iocharset : "iso8859-1";
s->u.isofs_sb.s_nls_iocharset = load_nls(p); sbi->s_nls_iocharset = load_nls(p);
if (! s->u.isofs_sb.s_nls_iocharset) { if (! sbi->s_nls_iocharset) {
/* Fail only if explicit charset specified */ /* Fail only if explicit charset specified */
if (opt.iocharset) if (opt.iocharset)
goto out_unlock; goto out_freesbi;
s->u.isofs_sb.s_nls_iocharset = load_nls_default(); sbi->s_nls_iocharset = load_nls_default();
} }
} }
#endif #endif
s->s_op = &isofs_sops; s->s_op = &isofs_sops;
s->u.isofs_sb.s_mapping = opt.map; sbi->s_mapping = opt.map;
s->u.isofs_sb.s_rock = (opt.rock == 'y' ? 2 : 0); sbi->s_rock = (opt.rock == 'y' ? 2 : 0);
s->u.isofs_sb.s_rock_offset = -1; /* initial offset, will guess until SP is found*/ sbi->s_rock_offset = -1; /* initial offset, will guess until SP is found*/
s->u.isofs_sb.s_cruft = opt.cruft; sbi->s_cruft = opt.cruft;
s->u.isofs_sb.s_unhide = opt.unhide; sbi->s_unhide = opt.unhide;
s->u.isofs_sb.s_uid = opt.uid; sbi->s_uid = opt.uid;
s->u.isofs_sb.s_gid = opt.gid; sbi->s_gid = opt.gid;
s->u.isofs_sb.s_utf8 = opt.utf8; sbi->s_utf8 = opt.utf8;
s->u.isofs_sb.s_nocompress = opt.nocompress; sbi->s_nocompress = opt.nocompress;
/* /*
* It would be incredibly stupid to allow people to mark every file * It would be incredibly stupid to allow people to mark every file
* on the disk as suid, so we merely allow them to set the default * on the disk as suid, so we merely allow them to set the default
* permissions. * permissions.
*/ */
s->u.isofs_sb.s_mode = opt.mode & 0777; sbi->s_mode = opt.mode & 0777;
/* /*
* Read the root inode, which _may_ result in changing * Read the root inode, which _may_ result in changing
* the s_rock flag. Once we have the final s_rock value, * the s_rock flag. Once we have the final s_rock value,
* we then decide whether to use the Joliet descriptor. * we then decide whether to use the Joliet descriptor.
*/ */
inode = iget(s, s->u.isofs_sb.s_firstdatazone); inode = iget(s, sbi->s_firstdatazone);
/* /*
* If this disk has both Rock Ridge and Joliet on it, then we * If this disk has both Rock Ridge and Joliet on it, then we
...@@ -807,16 +815,16 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) ...@@ -807,16 +815,16 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
* CD with Unicode names. Until someone sees such a beast, it * CD with Unicode names. Until someone sees such a beast, it
* will not be supported. * will not be supported.
*/ */
if (s->u.isofs_sb.s_rock == 1) { if (sbi->s_rock == 1) {
joliet_level = 0; joliet_level = 0;
} else if (joliet_level) { } else if (joliet_level) {
s->u.isofs_sb.s_rock = 0; sbi->s_rock = 0;
if (s->u.isofs_sb.s_firstdatazone != first_data_zone) { if (sbi->s_firstdatazone != first_data_zone) {
s->u.isofs_sb.s_firstdatazone = first_data_zone; sbi->s_firstdatazone = first_data_zone;
printk(KERN_DEBUG printk(KERN_DEBUG
"ISOFS: changing to secondary root\n"); "ISOFS: changing to secondary root\n");
iput(inode); iput(inode);
inode = iget(s, s->u.isofs_sb.s_firstdatazone); inode = iget(s, sbi->s_firstdatazone);
} }
} }
...@@ -825,7 +833,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) ...@@ -825,7 +833,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
if (joliet_level) opt.check = 'r'; if (joliet_level) opt.check = 'r';
else opt.check = 's'; else opt.check = 's';
} }
s->u.isofs_sb.s_joliet_level = joliet_level; sbi->s_joliet_level = joliet_level;
/* check the root inode */ /* check the root inode */
if (!inode) if (!inode)
...@@ -855,18 +863,18 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) ...@@ -855,18 +863,18 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
out_iput: out_iput:
iput(inode); iput(inode);
#ifdef CONFIG_JOLIET #ifdef CONFIG_JOLIET
if (s->u.isofs_sb.s_nls_iocharset) if (sbi->s_nls_iocharset)
unload_nls(s->u.isofs_sb.s_nls_iocharset); unload_nls(sbi->s_nls_iocharset);
#endif #endif
goto out_unlock; goto out_freesbi;
out_no_read: out_no_read:
printk(KERN_WARNING "isofs_fill_super: " printk(KERN_WARNING "isofs_fill_super: "
"bread failed, dev=%s, iso_blknum=%d, block=%d\n", "bread failed, dev=%s, iso_blknum=%d, block=%d\n",
s->s_id, iso_blknum, block); s->s_id, iso_blknum, block);
goto out_unlock; goto out_freesbi;
out_bad_zone_size: out_bad_zone_size:
printk(KERN_WARNING "Bad logical zone size %ld\n", printk(KERN_WARNING "Bad logical zone size %ld\n",
s->u.isofs_sb.s_log_zone_size); sbi->s_log_zone_size);
goto out_freebh; goto out_freebh;
out_bad_size: out_bad_size:
printk(KERN_WARNING "Logical zone size(%d) < hardware blocksize(%u)\n", printk(KERN_WARNING "Logical zone size(%d) < hardware blocksize(%u)\n",
...@@ -883,7 +891,9 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) ...@@ -883,7 +891,9 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
out_freebh: out_freebh:
brelse(bh); brelse(bh);
out_unlock: out_freesbi:
kfree(sbi);
s->u.generic_sbp = NULL;
return -EINVAL; return -EINVAL;
} }
...@@ -891,11 +901,11 @@ static int isofs_statfs (struct super_block *sb, struct statfs *buf) ...@@ -891,11 +901,11 @@ static int isofs_statfs (struct super_block *sb, struct statfs *buf)
{ {
buf->f_type = ISOFS_SUPER_MAGIC; buf->f_type = ISOFS_SUPER_MAGIC;
buf->f_bsize = sb->s_blocksize; buf->f_bsize = sb->s_blocksize;
buf->f_blocks = (sb->u.isofs_sb.s_nzones buf->f_blocks = (ISOFS_SB(sb)->s_nzones
<< (sb->u.isofs_sb.s_log_zone_size - sb->s_blocksize_bits)); << (ISOFS_SB(sb)->s_log_zone_size - sb->s_blocksize_bits));
buf->f_bfree = 0; buf->f_bfree = 0;
buf->f_bavail = 0; buf->f_bavail = 0;
buf->f_files = sb->u.isofs_sb.s_ninodes; buf->f_files = ISOFS_SB(sb)->s_ninodes;
buf->f_ffree = 0; buf->f_ffree = 0;
buf->f_namelen = NAME_MAX; buf->f_namelen = NAME_MAX;
return 0; return 0;
...@@ -1058,7 +1068,7 @@ static int isofs_read_level3_size(struct inode * inode) ...@@ -1058,7 +1068,7 @@ static int isofs_read_level3_size(struct inode * inode)
{ {
unsigned long f_pos = inode->i_ino; unsigned long f_pos = inode->i_ino;
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
int high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra; int high_sierra = ISOFS_SB(inode->i_sb)->s_high_sierra;
struct buffer_head * bh = NULL; struct buffer_head * bh = NULL;
unsigned long block, offset; unsigned long block, offset;
int i = 0; int i = 0;
...@@ -1157,9 +1167,10 @@ static int isofs_read_level3_size(struct inode * inode) ...@@ -1157,9 +1167,10 @@ static int isofs_read_level3_size(struct inode * inode)
static void isofs_read_inode(struct inode * inode) static void isofs_read_inode(struct inode * inode)
{ {
struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb;
struct isofs_sb_info *sbi = ISOFS_SB(sb);
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
int block = inode->i_ino >> ISOFS_BUFFER_BITS(inode); int block = inode->i_ino >> ISOFS_BUFFER_BITS(inode);
int high_sierra = sb->u.isofs_sb.s_high_sierra; int high_sierra = sbi->s_high_sierra;
struct buffer_head * bh = NULL; struct buffer_head * bh = NULL;
struct iso_directory_record * de; struct iso_directory_record * de;
struct iso_directory_record * tmpde = NULL; struct iso_directory_record * tmpde = NULL;
...@@ -1205,7 +1216,7 @@ static void isofs_read_inode(struct inode * inode) ...@@ -1205,7 +1216,7 @@ static void isofs_read_inode(struct inode * inode)
do it the hard way. */ do it the hard way. */
} else { } else {
/* Everybody gets to read the file. */ /* Everybody gets to read the file. */
inode->i_mode = inode->i_sb->u.isofs_sb.s_mode; inode->i_mode = sbi->s_mode;
inode->i_nlink = 1; inode->i_nlink = 1;
inode->i_mode |= S_IFREG; inode->i_mode |= S_IFREG;
/* If there are no periods in the name, /* If there are no periods in the name,
...@@ -1217,8 +1228,8 @@ static void isofs_read_inode(struct inode * inode) ...@@ -1217,8 +1228,8 @@ static void isofs_read_inode(struct inode * inode)
if(i == de->name_len[0] || de->name[i] == ';') if(i == de->name_len[0] || de->name[i] == ';')
inode->i_mode |= S_IXUGO; /* execute permission */ inode->i_mode |= S_IXUGO; /* execute permission */
} }
inode->i_uid = inode->i_sb->u.isofs_sb.s_uid; inode->i_uid = sbi->s_uid;
inode->i_gid = inode->i_sb->u.isofs_sb.s_gid; inode->i_gid = sbi->s_gid;
inode->i_blocks = inode->i_blksize = 0; inode->i_blocks = inode->i_blksize = 0;
ei->i_format_parm[0] = 0; ei->i_format_parm[0] = 0;
...@@ -1241,10 +1252,10 @@ static void isofs_read_inode(struct inode * inode) ...@@ -1241,10 +1252,10 @@ static void isofs_read_inode(struct inode * inode)
* legal. Do not prevent to use DVD's schilling@fokus.gmd.de * legal. Do not prevent to use DVD's schilling@fokus.gmd.de
*/ */
if ((inode->i_size < 0 || inode->i_size > 0x7FFFFFFE) && if ((inode->i_size < 0 || inode->i_size > 0x7FFFFFFE) &&
inode->i_sb->u.isofs_sb.s_cruft == 'n') { sbi->s_cruft == 'n') {
printk(KERN_WARNING "Warning: defective CD-ROM. " printk(KERN_WARNING "Warning: defective CD-ROM. "
"Enabling \"cruft\" mount option.\n"); "Enabling \"cruft\" mount option.\n");
inode->i_sb->u.isofs_sb.s_cruft = 'y'; sbi->s_cruft = 'y';
} }
/* /*
...@@ -1254,7 +1265,7 @@ static void isofs_read_inode(struct inode * inode) ...@@ -1254,7 +1265,7 @@ static void isofs_read_inode(struct inode * inode)
* on the CDROM. * on the CDROM.
*/ */
if (inode->i_sb->u.isofs_sb.s_cruft == 'y' && if (sbi->s_cruft == 'y' &&
inode->i_size & 0xff000000) { inode->i_size & 0xff000000) {
inode->i_size &= 0x00ffffff; inode->i_size &= 0x00ffffff;
} }
...@@ -1298,8 +1309,8 @@ static void isofs_read_inode(struct inode * inode) ...@@ -1298,8 +1309,8 @@ static void isofs_read_inode(struct inode * inode)
if (!high_sierra) { if (!high_sierra) {
parse_rock_ridge_inode(de, inode); parse_rock_ridge_inode(de, inode);
/* if we want uid/gid set, override the rock ridge setting */ /* if we want uid/gid set, override the rock ridge setting */
test_and_set_uid(&inode->i_uid, inode->i_sb->u.isofs_sb.s_uid); test_and_set_uid(&inode->i_uid, sbi->s_uid);
test_and_set_gid(&inode->i_gid, inode->i_sb->u.isofs_sb.s_gid); test_and_set_gid(&inode->i_gid, sbi->s_gid);
} }
/* get the volume sequence number */ /* get the volume sequence number */
...@@ -1311,17 +1322,17 @@ static void isofs_read_inode(struct inode * inode) ...@@ -1311,17 +1322,17 @@ static void isofs_read_inode(struct inode * inode)
* of which is limiting the file size to 16Mb. Thus we silently allow * of which is limiting the file size to 16Mb. Thus we silently allow
* volume numbers of 0 to go through without complaining. * volume numbers of 0 to go through without complaining.
*/ */
if (inode->i_sb->u.isofs_sb.s_cruft == 'n' && if (sbi->s_cruft == 'n' &&
(volume_seq_no != 0) && (volume_seq_no != 1)) { (volume_seq_no != 0) && (volume_seq_no != 1)) {
printk(KERN_WARNING "Warning: defective CD-ROM " printk(KERN_WARNING "Warning: defective CD-ROM "
"(volume sequence number %d). " "(volume sequence number %d). "
"Enabling \"cruft\" mount option.\n", volume_seq_no); "Enabling \"cruft\" mount option.\n", volume_seq_no);
inode->i_sb->u.isofs_sb.s_cruft = 'y'; sbi->s_cruft = 'y';
} }
/* Install the inode operations vector */ /* Install the inode operations vector */
#ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS #ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS
if (inode->i_sb->u.isofs_sb.s_cruft != 'y' && if (sbi->s_cruft != 'y' &&
(volume_seq_no != 0) && (volume_seq_no != 1)) { (volume_seq_no != 0) && (volume_seq_no != 1)) {
printk(KERN_WARNING "Multi-volume CD somehow got mounted.\n"); printk(KERN_WARNING "Multi-volume CD somehow got mounted.\n");
} else } else
......
...@@ -77,8 +77,8 @@ get_joliet_filename(struct iso_directory_record * de, unsigned char *outname, st ...@@ -77,8 +77,8 @@ get_joliet_filename(struct iso_directory_record * de, unsigned char *outname, st
struct nls_table *nls; struct nls_table *nls;
unsigned char len = 0; unsigned char len = 0;
utf8 = inode->i_sb->u.isofs_sb.s_utf8; utf8 = ISOFS_SB(inode->i_sb)->s_utf8;
nls = inode->i_sb->u.isofs_sb.s_nls_iocharset; nls = ISOFS_SB(inode->i_sb)->s_nls_iocharset;
if (utf8) { if (utf8) {
len = wcsntombs_be(outname, de->name, len = wcsntombs_be(outname, de->name,
......
...@@ -65,6 +65,7 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry, ...@@ -65,6 +65,7 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
unsigned char bufbits = ISOFS_BUFFER_BITS(dir); unsigned char bufbits = ISOFS_BUFFER_BITS(dir);
unsigned int block, f_pos, offset; unsigned int block, f_pos, offset;
struct buffer_head * bh = NULL; struct buffer_head * bh = NULL;
struct isofs_sb_info *sbi = ISOFS_SB(dir->i_sb);
if (!ISOFS_I(dir)->i_first_extent) if (!ISOFS_I(dir)->i_first_extent)
return 0; return 0;
...@@ -120,19 +121,19 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry, ...@@ -120,19 +121,19 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
dlen = de->name_len[0]; dlen = de->name_len[0];
dpnt = de->name; dpnt = de->name;
if (dir->i_sb->u.isofs_sb.s_rock && if (sbi->s_rock &&
((i = get_rock_ridge_filename(de, tmpname, dir)))) { ((i = get_rock_ridge_filename(de, tmpname, dir)))) {
dlen = i; /* possibly -1 */ dlen = i; /* possibly -1 */
dpnt = tmpname; dpnt = tmpname;
#ifdef CONFIG_JOLIET #ifdef CONFIG_JOLIET
} else if (dir->i_sb->u.isofs_sb.s_joliet_level) { } else if (sbi->s_joliet_level) {
dlen = get_joliet_filename(de, tmpname, dir); dlen = get_joliet_filename(de, tmpname, dir);
dpnt = tmpname; dpnt = tmpname;
#endif #endif
} else if (dir->i_sb->u.isofs_sb.s_mapping == 'a') { } else if (sbi->s_mapping == 'a') {
dlen = get_acorn_filename(de, tmpname, dir); dlen = get_acorn_filename(de, tmpname, dir);
dpnt = tmpname; dpnt = tmpname;
} else if (dir->i_sb->u.isofs_sb.s_mapping == 'n') { } else if (sbi->s_mapping == 'n') {
dlen = isofs_name_translate(de, tmpname, dir); dlen = isofs_name_translate(de, tmpname, dir);
dpnt = tmpname; dpnt = tmpname;
} }
...@@ -142,8 +143,8 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry, ...@@ -142,8 +143,8 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
*/ */
match = 0; match = 0;
if (dlen > 0 && if (dlen > 0 &&
(!(de->flags[-dir->i_sb->u.isofs_sb.s_high_sierra] & 5) (!(de->flags[-sbi->s_high_sierra] & 5)
|| dir->i_sb->u.isofs_sb.s_unhide == 'y')) || sbi->s_unhide == 'y'))
{ {
match = (isofs_cmp(dentry,dpnt,dlen) == 0); match = (isofs_cmp(dentry,dpnt,dlen) == 0);
} }
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#define CHECK_SP(FAIL) \ #define CHECK_SP(FAIL) \
if(rr->u.SP.magic[0] != 0xbe) FAIL; \ if(rr->u.SP.magic[0] != 0xbe) FAIL; \
if(rr->u.SP.magic[1] != 0xef) FAIL; \ if(rr->u.SP.magic[1] != 0xef) FAIL; \
inode->i_sb->u.isofs_sb.s_rock_offset=rr->u.SP.skip; ISOFS_SB(inode->i_sb)->s_rock_offset=rr->u.SP.skip;
/* We define a series of macros because each function must do exactly the /* We define a series of macros because each function must do exactly the
same thing in certain places. We use the macros to ensure that everything same thing in certain places. We use the macros to ensure that everything
is done correctly */ is done correctly */
...@@ -51,10 +51,10 @@ ...@@ -51,10 +51,10 @@
if(LEN & 1) LEN++; \ if(LEN & 1) LEN++; \
CHR = ((unsigned char *) DE) + LEN; \ CHR = ((unsigned char *) DE) + LEN; \
LEN = *((unsigned char *) DE) - LEN; \ LEN = *((unsigned char *) DE) - LEN; \
if (inode->i_sb->u.isofs_sb.s_rock_offset!=-1) \ if (ISOFS_SB(inode->i_sb)->s_rock_offset!=-1) \
{ \ { \
LEN-=inode->i_sb->u.isofs_sb.s_rock_offset; \ LEN-=ISOFS_SB(inode->i_sb)->s_rock_offset; \
CHR+=inode->i_sb->u.isofs_sb.s_rock_offset; \ CHR+=ISOFS_SB(inode->i_sb)->s_rock_offset; \
if (LEN<0) LEN=0; \ if (LEN<0) LEN=0; \
} \ } \
} }
...@@ -102,7 +102,7 @@ int find_rock_ridge_relocation(struct iso_directory_record * de, ...@@ -102,7 +102,7 @@ int find_rock_ridge_relocation(struct iso_directory_record * de,
/* Return value if we do not find appropriate record. */ /* Return value if we do not find appropriate record. */
retval = isonum_733 (de->extent); retval = isonum_733 (de->extent);
if (!inode->i_sb->u.isofs_sb.s_rock) return retval; if (!ISOFS_SB(inode->i_sb)->s_rock) return retval;
SETUP_ROCK_RIDGE(de, chr, len); SETUP_ROCK_RIDGE(de, chr, len);
repeat: repeat:
...@@ -162,7 +162,7 @@ int get_rock_ridge_filename(struct iso_directory_record * de, ...@@ -162,7 +162,7 @@ int get_rock_ridge_filename(struct iso_directory_record * de,
CONTINUE_DECLS; CONTINUE_DECLS;
int retnamlen = 0, truncate=0; int retnamlen = 0, truncate=0;
if (!inode->i_sb->u.isofs_sb.s_rock) return 0; if (!ISOFS_SB(inode->i_sb)->s_rock) return 0;
*retname = 0; *retname = 0;
SETUP_ROCK_RIDGE(de, chr, len); SETUP_ROCK_RIDGE(de, chr, len);
...@@ -234,7 +234,7 @@ int parse_rock_ridge_inode_internal(struct iso_directory_record * de, ...@@ -234,7 +234,7 @@ int parse_rock_ridge_inode_internal(struct iso_directory_record * de,
int symlink_len = 0; int symlink_len = 0;
CONTINUE_DECLS; CONTINUE_DECLS;
if (!inode->i_sb->u.isofs_sb.s_rock) return 0; if (!ISOFS_SB(inode->i_sb)->s_rock) return 0;
SETUP_ROCK_RIDGE(de, chr, len); SETUP_ROCK_RIDGE(de, chr, len);
if (regard_xa) if (regard_xa)
...@@ -272,7 +272,7 @@ int parse_rock_ridge_inode_internal(struct iso_directory_record * de, ...@@ -272,7 +272,7 @@ int parse_rock_ridge_inode_internal(struct iso_directory_record * de,
CHECK_CE; CHECK_CE;
break; break;
case SIG('E','R'): case SIG('E','R'):
inode->i_sb->u.isofs_sb.s_rock = 1; ISOFS_SB(inode->i_sb)->s_rock = 1;
printk(KERN_DEBUG "ISO 9660 Extensions: "); printk(KERN_DEBUG "ISO 9660 Extensions: ");
{ int p; { int p;
for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]); for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]);
...@@ -368,7 +368,7 @@ int parse_rock_ridge_inode_internal(struct iso_directory_record * de, ...@@ -368,7 +368,7 @@ int parse_rock_ridge_inode_internal(struct iso_directory_record * de,
ISOFS_I(inode)->i_first_extent = isonum_733(rr->u.CL.location); ISOFS_I(inode)->i_first_extent = isonum_733(rr->u.CL.location);
reloc = iget(inode->i_sb, reloc = iget(inode->i_sb,
(ISOFS_I(inode)->i_first_extent << (ISOFS_I(inode)->i_first_extent <<
inode -> i_sb -> u.isofs_sb.s_log_zone_size)); ISOFS_SB(inode->i_sb)->s_log_zone_size));
if (!reloc) if (!reloc)
goto out; goto out;
inode->i_mode = reloc->i_mode; inode->i_mode = reloc->i_mode;
...@@ -385,7 +385,7 @@ int parse_rock_ridge_inode_internal(struct iso_directory_record * de, ...@@ -385,7 +385,7 @@ int parse_rock_ridge_inode_internal(struct iso_directory_record * de,
break; break;
#ifdef CONFIG_ZISOFS #ifdef CONFIG_ZISOFS
case SIG('Z','F'): case SIG('Z','F'):
if ( !inode->i_sb->u.isofs_sb.s_nocompress ) { if ( !ISOFS_SB(inode->i_sb)->s_nocompress ) {
int algo; int algo;
algo = isonum_721(rr->u.ZF.algorithm); algo = isonum_721(rr->u.ZF.algorithm);
if ( algo == SIG('p','z') ) { if ( algo == SIG('p','z') ) {
...@@ -478,8 +478,8 @@ int parse_rock_ridge_inode(struct iso_directory_record * de, ...@@ -478,8 +478,8 @@ int parse_rock_ridge_inode(struct iso_directory_record * de,
int result=parse_rock_ridge_inode_internal(de,inode,0); int result=parse_rock_ridge_inode_internal(de,inode,0);
/* if rockridge flag was reset and we didn't look for attributes /* if rockridge flag was reset and we didn't look for attributes
* behind eventual XA attributes, have a look there */ * behind eventual XA attributes, have a look there */
if ((inode->i_sb->u.isofs_sb.s_rock_offset==-1) if ((ISOFS_SB(inode->i_sb)->s_rock_offset==-1)
&&(inode->i_sb->u.isofs_sb.s_rock==2)) &&(ISOFS_SB(inode->i_sb)->s_rock==2))
{ {
result=parse_rock_ridge_inode_internal(de,inode,14); result=parse_rock_ridge_inode_internal(de,inode,14);
}; };
...@@ -506,7 +506,7 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page) ...@@ -506,7 +506,7 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
unsigned char *chr; unsigned char *chr;
struct rock_ridge *rr; struct rock_ridge *rr;
if (!inode->i_sb->u.isofs_sb.s_rock) if (!ISOFS_SB(inode->i_sb)->s_rock)
panic ("Cannot have symlink with high sierra variant of iso filesystem\n"); panic ("Cannot have symlink with high sierra variant of iso filesystem\n");
block = inode->i_ino >> bufbits; block = inode->i_ino >> bufbits;
......
...@@ -25,235 +25,16 @@ ...@@ -25,235 +25,16 @@
#include <linux/locks.h> #include <linux/locks.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/devfs_fs_kernel.h> #include <linux/devfs_fs_kernel.h>
#include <linux/major.h>
#include <linux/acct.h> #include <linux/acct.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/kmod.h> void get_filesystem(struct file_system_type *fs);
#define __NO_VERSION__ void put_filesystem(struct file_system_type *fs);
#include <linux/module.h> struct file_system_type *get_fs_type(const char *name);
LIST_HEAD(super_blocks); LIST_HEAD(super_blocks);
spinlock_t sb_lock = SPIN_LOCK_UNLOCKED; spinlock_t sb_lock = SPIN_LOCK_UNLOCKED;
/*
* Handling of filesystem drivers list.
* Rules:
* Inclusion to/removals from/scanning of list are protected by spinlock.
* During the unload module must call unregister_filesystem().
* We can access the fields of list element if:
* 1) spinlock is held or
* 2) we hold the reference to the module.
* The latter can be guaranteed by call of try_inc_mod_count(); if it
* returned 0 we must skip the element, otherwise we got the reference.
* Once the reference is obtained we can drop the spinlock.
*/
static struct file_system_type *file_systems;
static rwlock_t file_systems_lock = RW_LOCK_UNLOCKED;
/* WARNING: This can be used only if we _already_ own a reference */
static void get_filesystem(struct file_system_type *fs)
{
if (fs->owner)
__MOD_INC_USE_COUNT(fs->owner);
}
static void put_filesystem(struct file_system_type *fs)
{
if (fs->owner)
__MOD_DEC_USE_COUNT(fs->owner);
}
static struct file_system_type **find_filesystem(const char *name)
{
struct file_system_type **p;
for (p=&file_systems; *p; p=&(*p)->next)
if (strcmp((*p)->name,name) == 0)
break;
return p;
}
/**
* register_filesystem - register a new filesystem
* @fs: the file system structure
*
* Adds the file system passed to the list of file systems the kernel
* is aware of for mount and other syscalls. Returns 0 on success,
* or a negative errno code on an error.
*
* The &struct file_system_type that is passed is linked into the kernel
* structures and must not be freed until the file system has been
* unregistered.
*/
int register_filesystem(struct file_system_type * fs)
{
int res = 0;
struct file_system_type ** p;
if (!fs)
return -EINVAL;
if (fs->next)
return -EBUSY;
INIT_LIST_HEAD(&fs->fs_supers);
write_lock(&file_systems_lock);
p = find_filesystem(fs->name);
if (*p)
res = -EBUSY;
else
*p = fs;
write_unlock(&file_systems_lock);
return res;
}
/**
* unregister_filesystem - unregister a file system
* @fs: filesystem to unregister
*
* Remove a file system that was previously successfully registered
* with the kernel. An error is returned if the file system is not found.
* Zero is returned on a success.
*
* Once this function has returned the &struct file_system_type structure
* may be freed or reused.
*/
int unregister_filesystem(struct file_system_type * fs)
{
struct file_system_type ** tmp;
write_lock(&file_systems_lock);
tmp = &file_systems;
while (*tmp) {
if (fs == *tmp) {
*tmp = fs->next;
fs->next = NULL;
write_unlock(&file_systems_lock);
return 0;
}
tmp = &(*tmp)->next;
}
write_unlock(&file_systems_lock);
return -EINVAL;
}
static int fs_index(const char * __name)
{
struct file_system_type * tmp;
char * name;
int err, index;
name = getname(__name);
err = PTR_ERR(name);
if (IS_ERR(name))
return err;
err = -EINVAL;
read_lock(&file_systems_lock);
for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
if (strcmp(tmp->name,name) == 0) {
err = index;
break;
}
}
read_unlock(&file_systems_lock);
putname(name);
return err;
}
static int fs_name(unsigned int index, char * buf)
{
struct file_system_type * tmp;
int len, res;
read_lock(&file_systems_lock);
for (tmp = file_systems; tmp; tmp = tmp->next, index--)
if (index <= 0 && try_inc_mod_count(tmp->owner))
break;
read_unlock(&file_systems_lock);
if (!tmp)
return -EINVAL;
/* OK, we got the reference, so we can safely block */
len = strlen(tmp->name) + 1;
res = copy_to_user(buf, tmp->name, len) ? -EFAULT : 0;
put_filesystem(tmp);
return res;
}
static int fs_maxindex(void)
{
struct file_system_type * tmp;
int index;
read_lock(&file_systems_lock);
for (tmp = file_systems, index = 0 ; tmp ; tmp = tmp->next, index++)
;
read_unlock(&file_systems_lock);
return index;
}
/*
* Whee.. Weird sysv syscall.
*/
asmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2)
{
int retval = -EINVAL;
switch (option) {
case 1:
retval = fs_index((const char *) arg1);
break;
case 2:
retval = fs_name(arg1, (char *) arg2);
break;
case 3:
retval = fs_maxindex();
break;
}
return retval;
}
int get_filesystem_list(char * buf)
{
int len = 0;
struct file_system_type * tmp;
read_lock(&file_systems_lock);
tmp = file_systems;
while (tmp && len < PAGE_SIZE - 80) {
len += sprintf(buf+len, "%s\t%s\n",
(tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev",
tmp->name);
tmp = tmp->next;
}
read_unlock(&file_systems_lock);
return len;
}
struct file_system_type *get_fs_type(const char *name)
{
struct file_system_type *fs;
read_lock(&file_systems_lock);
fs = *(find_filesystem(name));
if (fs && !try_inc_mod_count(fs->owner))
fs = NULL;
read_unlock(&file_systems_lock);
if (!fs && (request_module(name) == 0)) {
read_lock(&file_systems_lock);
fs = *(find_filesystem(name));
if (fs && !try_inc_mod_count(fs->owner))
fs = NULL;
read_unlock(&file_systems_lock);
}
return fs;
}
/** /**
* alloc_super - create new superblock * alloc_super - create new superblock
* *
......
...@@ -1413,12 +1413,17 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) ...@@ -1413,12 +1413,17 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
struct inode *inode=NULL; struct inode *inode=NULL;
struct udf_options uopt; struct udf_options uopt;
lb_addr rootdir, fileset; lb_addr rootdir, fileset;
struct udf_sb_info *sbi;
uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT); uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT);
uopt.uid = -1; uopt.uid = -1;
uopt.gid = -1; uopt.gid = -1;
uopt.umask = 0; uopt.umask = 0;
sbi = kmalloc(sizeof(struct udf_sb_info), GFP_KERNEL);
if (!sbi)
return -ENOMEM;
sb->u.generic_sbp = sbi;
memset(UDF_SB(sb), 0x00, sizeof(struct udf_sb_info)); memset(UDF_SB(sb), 0x00, sizeof(struct udf_sb_info));
#if UDFFS_RW != 1 #if UDFFS_RW != 1
...@@ -1607,6 +1612,8 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) ...@@ -1607,6 +1612,8 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
udf_close_lvid(sb); udf_close_lvid(sb);
udf_release_data(UDF_SB_LVIDBH(sb)); udf_release_data(UDF_SB_LVIDBH(sb));
UDF_SB_FREE(sb); UDF_SB_FREE(sb);
kfree(sbi);
sb->u.generic_sbp = NULL;
return -EINVAL; return -EINVAL;
} }
...@@ -1697,6 +1704,8 @@ udf_put_super(struct super_block *sb) ...@@ -1697,6 +1704,8 @@ udf_put_super(struct super_block *sb)
udf_close_lvid(sb); udf_close_lvid(sb);
udf_release_data(UDF_SB_LVIDBH(sb)); udf_release_data(UDF_SB_LVIDBH(sb));
UDF_SB_FREE(sb); UDF_SB_FREE(sb);
kfree(sb->u.generic_sbp);
sb->u.generic_sbp = NULL;
} }
/* /*
......
...@@ -30,6 +30,11 @@ ...@@ -30,6 +30,11 @@
#define UDF_PART_FLAG_REWRITABLE 0x0040 #define UDF_PART_FLAG_REWRITABLE 0x0040
#define UDF_PART_FLAG_OVERWRITABLE 0x0080 #define UDF_PART_FLAG_OVERWRITABLE 0x0080
static inline struct udf_sb_info *UDF_SB(struct super_block *sb)
{
return sb->u.generic_sbp;
}
#define UDF_SB_FREE(X)\ #define UDF_SB_FREE(X)\
{\ {\
if (UDF_SB(X))\ if (UDF_SB(X))\
...@@ -39,7 +44,6 @@ ...@@ -39,7 +44,6 @@
UDF_SB_PARTMAPS(X) = NULL;\ UDF_SB_PARTMAPS(X) = NULL;\
}\ }\
} }
#define UDF_SB(X) (&((X)->u.udf_sb))
#define UDF_SB_ALLOC_PARTMAPS(X,Y)\ #define UDF_SB_ALLOC_PARTMAPS(X,Y)\
{\ {\
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/udf_fs_i.h>
#include <linux/udf_fs_sb.h>
#ifndef LINUX_VERSION_CODE #ifndef LINUX_VERSION_CODE
#include <linux/version.h> #include <linux/version.h>
...@@ -15,8 +17,6 @@ ...@@ -15,8 +17,6 @@
#if !defined(CONFIG_UDF_FS) && !defined(CONFIG_UDF_FS_MODULE) #if !defined(CONFIG_UDF_FS) && !defined(CONFIG_UDF_FS_MODULE)
#define CONFIG_UDF_FS_MODULE #define CONFIG_UDF_FS_MODULE
#include <linux/udf_fs_i.h>
#include <linux/udf_fs_sb.h>
#endif #endif
#include "udfend.h" #include "udfend.h"
......
...@@ -99,7 +99,6 @@ typedef struct siginfo { ...@@ -99,7 +99,6 @@ typedef struct siginfo {
/* /*
* si_code values * si_code values
* Digital reserves positive values for kernel-generated signals.
*/ */
#define SI_USER 0 /* sent by kill, sigsend, raise */ #define SI_USER 0 /* sent by kill, sigsend, raise */
#define SI_KERNEL 0x80 /* sent by the kernel from somewhere */ #define SI_KERNEL 0x80 /* sent by the kernel from somewhere */
...@@ -109,6 +108,7 @@ typedef struct siginfo { ...@@ -109,6 +108,7 @@ typedef struct siginfo {
#define SI_ASYNCIO -4 /* sent by AIO completion */ #define SI_ASYNCIO -4 /* sent by AIO completion */
#define SI_SIGIO -5 /* sent by queued SIGIO */ #define SI_SIGIO -5 /* sent by queued SIGIO */
#define SI_TKILL -6 /* sent by tkill system call */ #define SI_TKILL -6 /* sent by tkill system call */
#define SI_DETHREAD -7 /* sent by execve() killing subsidiary threads */
#define SI_FROMUSER(siptr) ((siptr)->si_code <= 0) #define SI_FROMUSER(siptr) ((siptr)->si_code <= 0)
#define SI_FROMKERNEL(siptr) ((siptr)->si_code > 0) #define SI_FROMKERNEL(siptr) ((siptr)->si_code > 0)
......
...@@ -22,6 +22,7 @@ struct thread_info { ...@@ -22,6 +22,7 @@ struct thread_info {
struct exec_domain *exec_domain; /* execution domain */ struct exec_domain *exec_domain; /* execution domain */
unsigned long flags; /* low level flags */ unsigned long flags; /* low level flags */
int cpu; /* cpu we're on */ int cpu; /* cpu we're on */
int preempt_count; /* not used at present */
}; };
/* /*
......
...@@ -648,7 +648,6 @@ struct quota_mount_options ...@@ -648,7 +648,6 @@ struct quota_mount_options
#include <linux/ext3_fs_sb.h> #include <linux/ext3_fs_sb.h>
#include <linux/hpfs_fs_sb.h> #include <linux/hpfs_fs_sb.h>
#include <linux/ntfs_fs_sb.h> #include <linux/ntfs_fs_sb.h>
#include <linux/iso_fs_sb.h>
#include <linux/sysv_fs_sb.h> #include <linux/sysv_fs_sb.h>
#include <linux/affs_fs_sb.h> #include <linux/affs_fs_sb.h>
#include <linux/ufs_fs_sb.h> #include <linux/ufs_fs_sb.h>
...@@ -657,7 +656,6 @@ struct quota_mount_options ...@@ -657,7 +656,6 @@ struct quota_mount_options
#include <linux/adfs_fs_sb.h> #include <linux/adfs_fs_sb.h>
#include <linux/reiserfs_fs_sb.h> #include <linux/reiserfs_fs_sb.h>
#include <linux/bfs_fs_sb.h> #include <linux/bfs_fs_sb.h>
#include <linux/udf_fs_sb.h>
extern struct list_head super_blocks; extern struct list_head super_blocks;
extern spinlock_t sb_lock; extern spinlock_t sb_lock;
...@@ -696,7 +694,6 @@ struct super_block { ...@@ -696,7 +694,6 @@ struct super_block {
struct ext3_sb_info ext3_sb; struct ext3_sb_info ext3_sb;
struct hpfs_sb_info hpfs_sb; struct hpfs_sb_info hpfs_sb;
struct ntfs_sb_info ntfs_sb; struct ntfs_sb_info ntfs_sb;
struct isofs_sb_info isofs_sb;
struct sysv_sb_info sysv_sb; struct sysv_sb_info sysv_sb;
struct affs_sb_info affs_sb; struct affs_sb_info affs_sb;
struct ufs_sb_info ufs_sb; struct ufs_sb_info ufs_sb;
...@@ -706,7 +703,6 @@ struct super_block { ...@@ -706,7 +703,6 @@ struct super_block {
struct adfs_sb_info adfs_sb; struct adfs_sb_info adfs_sb;
struct reiserfs_sb_info reiserfs_sb; struct reiserfs_sb_info reiserfs_sb;
struct bfs_sb_info bfs_sb; struct bfs_sb_info bfs_sb;
struct udf_sb_info udf_sb;
void *generic_sbp; void *generic_sbp;
} u; } u;
/* /*
......
...@@ -119,6 +119,7 @@ struct hiddev_usage_ref { ...@@ -119,6 +119,7 @@ struct hiddev_usage_ref {
__s32 value; __s32 value;
}; };
#define HID_FIELD_INDEX_NONE 0xffffffff
/* /*
* Protocol version. * Protocol version.
...@@ -143,6 +144,15 @@ struct hiddev_usage_ref { ...@@ -143,6 +144,15 @@ struct hiddev_usage_ref {
#define HIDIOCGUSAGE _IOWR('H', 0x0B, struct hiddev_usage_ref) #define HIDIOCGUSAGE _IOWR('H', 0x0B, struct hiddev_usage_ref)
#define HIDIOCSUSAGE _IOW('H', 0x0C, struct hiddev_usage_ref) #define HIDIOCSUSAGE _IOW('H', 0x0C, struct hiddev_usage_ref)
#define HIDIOCGUCODE _IOWR('H', 0x0D, struct hiddev_usage_ref) #define HIDIOCGUCODE _IOWR('H', 0x0D, struct hiddev_usage_ref)
#define HIDIOCGFLAG _IOR('H', 0x0E, int)
#define HIDIOCSFLAG _IOW('H', 0x0F, int)
/*
* Flags to be used in HIDIOCSFLAG
*/
#define HIDDEV_FLAG_UREF 0x1
#define HIDDEV_FLAG_REPORT 0x2
#define HIDDEV_FLAGS 0x3
/* To traverse the input report descriptor info for a HID device, perform the /* To traverse the input report descriptor info for a HID device, perform the
* following: * following:
...@@ -179,7 +189,7 @@ struct hiddev_usage_ref { ...@@ -179,7 +189,7 @@ struct hiddev_usage_ref {
#ifdef CONFIG_USB_HIDDEV #ifdef CONFIG_USB_HIDDEV
int hiddev_connect(struct hid_device *); int hiddev_connect(struct hid_device *);
void hiddev_disconnect(struct hid_device *); void hiddev_disconnect(struct hid_device *);
void hiddev_hid_event(struct hid_device *, unsigned int usage, int value); void hiddev_hid_event(struct hid_device *, struct hiddev_usage_ref *ref);
int __init hiddev_init(void); int __init hiddev_init(void);
void __exit hiddev_exit(void); void __exit hiddev_exit(void);
#else #else
......
...@@ -122,6 +122,7 @@ struct wanpipe_opt ...@@ -122,6 +122,7 @@ struct wanpipe_opt
unsigned poll_cnt; unsigned poll_cnt;
unsigned char force; /* Used to force sock release */ unsigned char force; /* Used to force sock release */
atomic_t packet_sent; atomic_t packet_sent;
unsigned short num;
}; };
#define wp_sk(__sk) ((struct wanpipe_opt *)(__sk)->protinfo) #define wp_sk(__sk) ((struct wanpipe_opt *)(__sk)->protinfo)
......
...@@ -160,7 +160,6 @@ struct iso_directory_record { ...@@ -160,7 +160,6 @@ struct iso_directory_record {
#define ISOFS_BUFFER_SIZE(INODE) ((INODE)->i_sb->s_blocksize) #define ISOFS_BUFFER_SIZE(INODE) ((INODE)->i_sb->s_blocksize)
#define ISOFS_BUFFER_BITS(INODE) ((INODE)->i_sb->s_blocksize_bits) #define ISOFS_BUFFER_BITS(INODE) ((INODE)->i_sb->s_blocksize_bits)
#define ISOFS_ZONE_BITS(INODE) ((INODE)->i_sb->u.isofs_sb.s_log_zone_size)
#define ISOFS_SUPER_MAGIC 0x9660 #define ISOFS_SUPER_MAGIC 0x9660
...@@ -171,6 +170,12 @@ struct iso_directory_record { ...@@ -171,6 +170,12 @@ struct iso_directory_record {
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <linux/iso_fs_i.h> #include <linux/iso_fs_i.h>
#include <linux/iso_fs_sb.h>
static inline struct isofs_sb_info *ISOFS_SB(struct super_block *sb)
{
return sb->u.generic_sbp;
}
static inline struct iso_inode_info *ISOFS_I(struct inode *inode) static inline struct iso_inode_info *ISOFS_I(struct inode *inode)
{ {
......
...@@ -38,7 +38,7 @@ MODULE_LICENSE("GPL"); ...@@ -38,7 +38,7 @@ MODULE_LICENSE("GPL");
static int kill_proto(const struct ip_conntrack *i, void *data) static int kill_proto(const struct ip_conntrack *i, void *data)
{ {
return (i->tuplehash[IP_CT_DIR_ORIGINAL].dst.protonum == return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum ==
*((u_int8_t *) data)); *((u_int8_t *) data));
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
* Alan Cox. * Alan Cox.
* X25 socket Author: Jonathan Naylor. * X25 socket Author: Jonathan Naylor.
* ============================================================================ * ============================================================================
* Mar 15, 2002 Arnaldo C. Melo o Use wp_sk()->num, as it isnt anymore in sock
* Apr 25, 2000 Nenad Corbic o Added the ability to send zero length packets. * Apr 25, 2000 Nenad Corbic o Added the ability to send zero length packets.
* Mar 13, 2000 Nenad Corbic o Added a tx buffer check via ioctl call. * Mar 13, 2000 Nenad Corbic o Added a tx buffer check via ioctl call.
* Mar 06, 2000 Nenad Corbic o Fixed the corrupt sock lcn problem. * Mar 06, 2000 Nenad Corbic o Fixed the corrupt sock lcn problem.
...@@ -164,11 +165,11 @@ static void dbg_kfree(void * v, int line) { ...@@ -164,11 +165,11 @@ static void dbg_kfree(void * v, int line) {
/* List of all wanpipe sockets. */ /* List of all wanpipe sockets. */
struct sock * wanpipe_sklist = NULL; struct sock* wanpipe_sklist;
static rwlock_t wanpipe_sklist_lock = RW_LOCK_UNLOCKED; static rwlock_t wanpipe_sklist_lock = RW_LOCK_UNLOCKED;
atomic_t wanpipe_socks_nr; atomic_t wanpipe_socks_nr;
static unsigned long wanpipe_tx_critical=0; static unsigned long wanpipe_tx_critical;
#if 0 #if 0
/* Private wanpipe socket structures. */ /* Private wanpipe socket structures. */
...@@ -187,9 +188,9 @@ struct wanpipe_opt ...@@ -187,9 +188,9 @@ struct wanpipe_opt
}; };
#endif #endif
static int sk_count=0; static int sk_count;
extern struct proto_ops wanpipe_ops; extern struct proto_ops wanpipe_ops;
static unsigned long find_free_critical=0; static unsigned long find_free_critical;
static void wanpipe_unlink_driver (struct sock *); static void wanpipe_unlink_driver (struct sock *);
static void wanpipe_link_driver (netdevice_t *,struct sock *sk); static void wanpipe_link_driver (netdevice_t *,struct sock *sk);
...@@ -400,9 +401,9 @@ static int wanpipe_listen_rcv (struct sk_buff *skb, struct sock *sk) ...@@ -400,9 +401,9 @@ static int wanpipe_listen_rcv (struct sk_buff *skb, struct sock *sk)
card->u.x.svc_to_dev_map[(chan->lcn%MAX_X25_LCN)] = dev; card->u.x.svc_to_dev_map[(chan->lcn%MAX_X25_LCN)] = dev;
newsk->zapped=0; newsk->zapped=0;
newsk->num = htons(X25_PROT); newwp->num = htons(X25_PROT);
if (wanpipe_do_bind(newsk,dev,newsk->num)){ if (wanpipe_do_bind(newsk, dev, newwp->num)) {
wanpipe_kill_sock_irq (newsk); wanpipe_kill_sock_irq (newsk);
release_device(dev); release_device(dev);
return -EINVAL; return -EINVAL;
...@@ -470,7 +471,7 @@ static struct sock *wanpipe_make_new(struct sock *osk) ...@@ -470,7 +471,7 @@ static struct sock *wanpipe_make_new(struct sock *osk)
sk->socket = osk->socket; sk->socket = osk->socket;
sk->priority = osk->priority; sk->priority = osk->priority;
sk->protocol = osk->protocol; sk->protocol = osk->protocol;
sk->num = osk->num; wp_sk(sk)->num = wp_sk(osk)->num;
sk->rcvbuf = osk->rcvbuf; sk->rcvbuf = osk->rcvbuf;
sk->sndbuf = osk->sndbuf; sk->sndbuf = osk->sndbuf;
sk->debug = osk->debug; sk->debug = osk->debug;
...@@ -566,9 +567,11 @@ static int wanpipe_sendmsg(struct socket *sock, struct msghdr *msg, int len, ...@@ -566,9 +567,11 @@ static int wanpipe_sendmsg(struct socket *sock, struct msghdr *msg, int len,
if (len < sizeof(x25api_hdr_t)) if (len < sizeof(x25api_hdr_t))
return -EINVAL; return -EINVAL;
wp = wp_sk(sk);
if (saddr == NULL) { if (saddr == NULL) {
ifindex = sk->bound_dev_if; ifindex = sk->bound_dev_if;
proto = sk->num; proto = wp->num;
addr = NULL; addr = NULL;
}else{ }else{
...@@ -648,7 +651,6 @@ static int wanpipe_sendmsg(struct socket *sock, struct msghdr *msg, int len, ...@@ -648,7 +651,6 @@ static int wanpipe_sendmsg(struct socket *sock, struct msghdr *msg, int len,
} }
skb_queue_tail(&sk->write_queue,skb); skb_queue_tail(&sk->write_queue,skb);
wp = wp_sk(sk);
atomic_inc(&wp->packet_sent); atomic_inc(&wp->packet_sent);
if (!(test_and_set_bit(0, &wp->timer))){ if (!(test_and_set_bit(0, &wp->timer))){
...@@ -998,7 +1000,8 @@ static int wanpipe_release(struct socket *sock, struct socket *peersock) ...@@ -998,7 +1000,8 @@ static int wanpipe_release(struct socket *sock, struct socket *peersock)
* Unhook packet receive handler. * Unhook packet receive handler.
*/ */
if (sk->num == htons(X25_PROT) && sk->state != WANSOCK_DISCONNECTED && sk->zapped){ if (wp->num == htons(X25_PROT) &&
sk->state != WANSOCK_DISCONNECTED && sk->zapped) {
netdevice_t *dev = dev_get_by_index(sk->bound_dev_if); netdevice_t *dev = dev_get_by_index(sk->bound_dev_if);
wanpipe_common_t *chan; wanpipe_common_t *chan;
if (dev){ if (dev){
...@@ -1206,7 +1209,8 @@ static void wanpipe_kill_sock_timer (unsigned long data) ...@@ -1206,7 +1209,8 @@ static void wanpipe_kill_sock_timer (unsigned long data)
write_unlock(&wanpipe_sklist_lock); write_unlock(&wanpipe_sklist_lock);
if (sk->num == htons(X25_PROT) && sk->state != WANSOCK_DISCONNECTED){ if (wp_sk(sk)->num == htons(X25_PROT) &&
sk->state != WANSOCK_DISCONNECTED){
netdevice_t *dev = dev_get_by_index(sk->bound_dev_if); netdevice_t *dev = dev_get_by_index(sk->bound_dev_if);
wanpipe_common_t *chan; wanpipe_common_t *chan;
if (dev){ if (dev){
...@@ -1352,6 +1356,7 @@ static void wanpipe_kill_sock_irq (struct sock *sk) ...@@ -1352,6 +1356,7 @@ static void wanpipe_kill_sock_irq (struct sock *sk)
static int wanpipe_do_bind(struct sock *sk, netdevice_t *dev, int protocol) static int wanpipe_do_bind(struct sock *sk, netdevice_t *dev, int protocol)
{ {
wanpipe_opt *wp = wp_sk(sk);
wanpipe_common_t *chan=NULL; wanpipe_common_t *chan=NULL;
int err=0; int err=0;
...@@ -1360,7 +1365,7 @@ static int wanpipe_do_bind(struct sock *sk, netdevice_t *dev, int protocol) ...@@ -1360,7 +1365,7 @@ static int wanpipe_do_bind(struct sock *sk, netdevice_t *dev, int protocol)
goto bind_unlock_exit; goto bind_unlock_exit;
} }
sk->num = protocol; wp->num = protocol;
if (protocol == 0){ if (protocol == 0){
release_device(dev); release_device(dev);
...@@ -1373,7 +1378,7 @@ static int wanpipe_do_bind(struct sock *sk, netdevice_t *dev, int protocol) ...@@ -1373,7 +1378,7 @@ static int wanpipe_do_bind(struct sock *sk, netdevice_t *dev, int protocol)
chan=dev->priv; chan=dev->priv;
sk->state = chan->state; sk->state = chan->state;
if (sk->num == htons(X25_PROT) && if (wp->num == htons(X25_PROT) &&
sk->state != WANSOCK_DISCONNECTED && sk->state != WANSOCK_DISCONNECTED &&
sk->state != WANSOCK_CONNECTING){ sk->state != WANSOCK_CONNECTING){
DBG_PRINTK(KERN_INFO DBG_PRINTK(KERN_INFO
...@@ -1388,7 +1393,7 @@ static int wanpipe_do_bind(struct sock *sk, netdevice_t *dev, int protocol) ...@@ -1388,7 +1393,7 @@ static int wanpipe_do_bind(struct sock *sk, netdevice_t *dev, int protocol)
sk->bound_dev_if = dev->ifindex; sk->bound_dev_if = dev->ifindex;
/* X25 Specific option */ /* X25 Specific option */
if (sk->num == htons(X25_PROT)) if (wp->num == htons(X25_PROT))
wp_sk(sk)->svc = chan->svc; wp_sk(sk)->svc = chan->svc;
} else { } else {
...@@ -1421,6 +1426,7 @@ static int wanpipe_bind(struct socket *sock, struct sockaddr *uaddr, int addr_le ...@@ -1421,6 +1426,7 @@ static int wanpipe_bind(struct socket *sock, struct sockaddr *uaddr, int addr_le
{ {
struct wan_sockaddr_ll *sll = (struct wan_sockaddr_ll*)uaddr; struct wan_sockaddr_ll *sll = (struct wan_sockaddr_ll*)uaddr;
struct sock *sk=sock->sk; struct sock *sk=sock->sk;
wanpipe_opt *wp = wp_sk(sk);
netdevice_t *dev = NULL; netdevice_t *dev = NULL;
sdla_t *card=NULL; sdla_t *card=NULL;
char name[15]; char name[15];
...@@ -1462,7 +1468,7 @@ static int wanpipe_bind(struct socket *sock, struct sockaddr *uaddr, int addr_le ...@@ -1462,7 +1468,7 @@ static int wanpipe_bind(struct socket *sock, struct sockaddr *uaddr, int addr_le
return err; return err;
if (sll->sll_protocol) if (sll->sll_protocol)
sk->num = sll->sll_protocol; wp->num = sll->sll_protocol;
sk->state = WANSOCK_BIND_LISTEN; sk->state = WANSOCK_BIND_LISTEN;
return 0; return 0;
...@@ -1509,7 +1515,7 @@ static int wanpipe_bind(struct socket *sock, struct sockaddr *uaddr, int addr_le ...@@ -1509,7 +1515,7 @@ static int wanpipe_bind(struct socket *sock, struct sockaddr *uaddr, int addr_le
return -EINVAL; return -EINVAL;
} }
return wanpipe_do_bind(sk, dev, sll->sll_protocol ? : sk->num); return wanpipe_do_bind(sk, dev, sll->sll_protocol ? : wp->num);
} }
/*============================================================ /*============================================================
...@@ -1613,7 +1619,7 @@ static int wanpipe_create(struct socket *sock, int protocol) ...@@ -1613,7 +1619,7 @@ static int wanpipe_create(struct socket *sock, int protocol)
sk->zapped=0; sk->zapped=0;
sk->family = PF_WANPIPE; sk->family = PF_WANPIPE;
sk->num = protocol; wp_sk(sk)->num = protocol;
sk->state = WANSOCK_DISCONNECTED; sk->state = WANSOCK_DISCONNECTED;
sk->ack_backlog = 0; sk->ack_backlog = 0;
sk->bound_dev_if=0; sk->bound_dev_if=0;
...@@ -1774,7 +1780,7 @@ static int wanpipe_getname(struct socket *sock, struct sockaddr *uaddr, ...@@ -1774,7 +1780,7 @@ static int wanpipe_getname(struct socket *sock, struct sockaddr *uaddr,
sll->sll_family = AF_WANPIPE; sll->sll_family = AF_WANPIPE;
sll->sll_ifindex = sk->bound_dev_if; sll->sll_ifindex = sk->bound_dev_if;
sll->sll_protocol = sk->num; sll->sll_protocol = wp_sk(sk)->num;
dev = dev_get_by_index(sk->bound_dev_if); dev = dev_get_by_index(sk->bound_dev_if);
if (dev) { if (dev) {
sll->sll_hatype = dev->type; sll->sll_hatype = dev->type;
...@@ -1836,7 +1842,8 @@ static int wanpipe_notifier(struct notifier_block *this, unsigned long msg, void ...@@ -1836,7 +1842,8 @@ static int wanpipe_notifier(struct notifier_block *this, unsigned long msg, void
} }
break; break;
case NETDEV_UP: case NETDEV_UP:
if (dev->ifindex == sk->bound_dev_if && sk->num && !sk->zapped) { if (dev->ifindex == sk->bound_dev_if &&
po->num && !sk->zapped) {
printk(KERN_INFO "wansock: Registering Device: %s\n", printk(KERN_INFO "wansock: Registering Device: %s\n",
dev->name); dev->name);
wanpipe_link_driver(dev,sk); wanpipe_link_driver(dev,sk);
...@@ -2242,7 +2249,7 @@ unsigned int wanpipe_poll(struct file * file, struct socket *sock, poll_table *w ...@@ -2242,7 +2249,7 @@ unsigned int wanpipe_poll(struct file * file, struct socket *sock, poll_table *w
* where multiple packets can be pending in the socket * where multiple packets can be pending in the socket
* transmit queue */ * transmit queue */
if (sk->num == htons(X25_PROT)){ if (wp_sk(sk)->num == htons(X25_PROT)) {
if (atomic_read(&wp_sk(sk)->packet_sent)) if (atomic_read(&wp_sk(sk)->packet_sent))
return mask; return mask;
} }
...@@ -2274,7 +2281,7 @@ static int wanpipe_listen(struct socket *sock, int backlog) ...@@ -2274,7 +2281,7 @@ static int wanpipe_listen(struct socket *sock, int backlog)
/* This is x25 specific area if protocol doesn't /* This is x25 specific area if protocol doesn't
* match, return error */ * match, return error */
if (sk->num != htons(X25_PROT)) if (wp_sk(sk)->num != htons(X25_PROT))
return -EINVAL; return -EINVAL;
if (sk->state == WANSOCK_BIND_LISTEN) { if (sk->state == WANSOCK_BIND_LISTEN) {
...@@ -2352,7 +2359,7 @@ static int wanpipe_exec_cmd(struct sock *sk, int cmd, unsigned int flags) ...@@ -2352,7 +2359,7 @@ static int wanpipe_exec_cmd(struct sock *sk, int cmd, unsigned int flags)
/* This is x25 specific area if protocol doesn't /* This is x25 specific area if protocol doesn't
* match, return error */ * match, return error */
if (sk->num != htons(X25_PROT)) if (wp->num != htons(X25_PROT))
return -EINVAL; return -EINVAL;
...@@ -2535,7 +2542,7 @@ static int wanpipe_accept(struct socket *sock, struct socket *newsock, int flags ...@@ -2535,7 +2542,7 @@ static int wanpipe_accept(struct socket *sock, struct socket *newsock, int flags
if (sk->state != WANSOCK_LISTEN) if (sk->state != WANSOCK_LISTEN)
return -EINVAL; return -EINVAL;
if (sk->num != htons(X25_PROT)) if (wp_sk(sk)->num != htons(X25_PROT))
return -EINVAL; return -EINVAL;
add_wait_queue(sk->sleep,&wait); add_wait_queue(sk->sleep,&wait);
...@@ -2628,7 +2635,7 @@ static int wanpipe_connect(struct socket *sock, struct sockaddr *uaddr, int addr ...@@ -2628,7 +2635,7 @@ static int wanpipe_connect(struct socket *sock, struct sockaddr *uaddr, int addr
netdevice_t *dev; netdevice_t *dev;
int err; int err;
if (sk->num != htons(X25_PROT)) if (wp_sk(sk)->num != htons(X25_PROT))
return -EINVAL; return -EINVAL;
if (sk->state == WANSOCK_CONNECTED) if (sk->state == WANSOCK_CONNECTED)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment