Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (94 commits)
  genetlink: fix netns vs. netlink table locking (2)
  3c59x: Get rid of "Trying to free already-free IRQ"
  tunnel: eliminate recursion field
  ems_pci: fix size of CAN controllers BAR mapping for CPC-PCI v2
  net: fix htmldocs sunrpc, clnt.c
  Phonet: error on broadcast sending (unimplemented)
  Phonet: fix race for port number in concurrent bind()
  pktgen: better scheduler friendliness
  pktgen: T_TERMINATE flag is unused
  ipv4: check optlen for IP_MULTICAST_IF option
  ath9k: Initialize txgain and rxgain for newer AR9287 chipsets.
  iwlagn: fix panic in iwl{5000,4965}_rx_reply_tx
  ath9k: Fix RFKILL bugs
  drivers/net/wireless: Use usb_endpoint_dir_out
  cfg80211: don't overwrite privacy setting
  wl12xx: fix kconfig/link errors
  rt2x00: fix the definition of rt2x00crypto_rx_insert_iv
  iwlwifi: reduce noise when skb allocation fails
  iwlwifi: do not send sync command while holding spinlock
  mac80211: fix DTIM setting
  ...
This commit is contained in:
Linus Torvalds 2009-09-25 07:22:11 -07:00
commit 5c3cc2084d
93 changed files with 2620 additions and 2919 deletions

View file

@ -757,6 +757,42 @@ void __init at91_add_device_ac97(struct ac97c_platform_data *data)
void __init at91_add_device_ac97(struct ac97c_platform_data *data) {} void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
#endif #endif
/* --------------------------------------------------------------------
* CAN Controller
* -------------------------------------------------------------------- */
#if defined(CONFIG_CAN_AT91) || defined(CONFIG_CAN_AT91_MODULE)
static struct resource can_resources[] = {
[0] = {
.start = AT91SAM9263_BASE_CAN,
.end = AT91SAM9263_BASE_CAN + SZ_16K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = AT91SAM9263_ID_CAN,
.end = AT91SAM9263_ID_CAN,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device at91sam9263_can_device = {
.name = "at91_can",
.id = -1,
.resource = can_resources,
.num_resources = ARRAY_SIZE(can_resources),
};
void __init at91_add_device_can(struct at91_can_data *data)
{
at91_set_A_periph(AT91_PIN_PA13, 0); /* CANTX */
at91_set_A_periph(AT91_PIN_PA14, 0); /* CANRX */
at91sam9263_can_device.dev.platform_data = data;
platform_device_register(&at91sam9263_can_device);
}
#else
void __init at91_add_device_can(struct at91_can_data *data) {}
#endif
/* -------------------------------------------------------------------- /* --------------------------------------------------------------------
* LCD Controller * LCD Controller

View file

@ -400,6 +400,23 @@ static struct gpio_led ek_pwm_led[] = {
} }
}; };
/*
* CAN
*/
static void sam9263ek_transceiver_switch(int on)
{
if (on) {
at91_set_gpio_output(AT91_PIN_PA18, 1); /* CANRXEN */
at91_set_gpio_output(AT91_PIN_PA19, 0); /* CANRS */
} else {
at91_set_gpio_output(AT91_PIN_PA18, 0); /* CANRXEN */
at91_set_gpio_output(AT91_PIN_PA19, 1); /* CANRS */
}
}
static struct at91_can_data ek_can_data = {
.transceiver_switch = sam9263ek_transceiver_switch,
};
static void __init ek_board_init(void) static void __init ek_board_init(void)
{ {
@ -431,6 +448,8 @@ static void __init ek_board_init(void)
/* LEDs */ /* LEDs */
at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds)); at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led)); at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
/* CAN */
at91_add_device_can(&ek_can_data);
} }
MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK") MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")

View file

@ -188,6 +188,12 @@ extern void __init at91_add_device_isi(void);
/* Touchscreen Controller */ /* Touchscreen Controller */
extern void __init at91_add_device_tsadcc(void); extern void __init at91_add_device_tsadcc(void);
/* CAN */
struct at91_can_data {
void (*transceiver_switch)(int on);
};
extern void __init at91_add_device_can(struct at91_can_data *data);
/* LEDs */ /* LEDs */
extern void __init at91_init_leds(u8 cpu_led, u8 timer_led); extern void __init at91_init_leds(u8 cpu_led, u8 timer_led);
extern void __init at91_gpio_leds(struct gpio_led *leds, int nr); extern void __init at91_gpio_leds(struct gpio_led *leds, int nr);

View file

@ -790,11 +790,15 @@ he_init_group(struct he_dev *he_dev, int group)
he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev, he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev,
CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys); CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys);
if (he_dev->rbps_base == NULL) { if (he_dev->rbps_base == NULL) {
hprintk("failed to alloc rbps\n"); hprintk("failed to alloc rbps_base\n");
return -ENOMEM; goto out_destroy_rbps_pool;
} }
memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp)); memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp));
he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL); he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL);
if (he_dev->rbps_virt == NULL) {
hprintk("failed to alloc rbps_virt\n");
goto out_free_rbps_base;
}
for (i = 0; i < CONFIG_RBPS_SIZE; ++i) { for (i = 0; i < CONFIG_RBPS_SIZE; ++i) {
dma_addr_t dma_handle; dma_addr_t dma_handle;
@ -802,7 +806,7 @@ he_init_group(struct he_dev *he_dev, int group)
cpuaddr = pci_pool_alloc(he_dev->rbps_pool, GFP_KERNEL|GFP_DMA, &dma_handle); cpuaddr = pci_pool_alloc(he_dev->rbps_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
if (cpuaddr == NULL) if (cpuaddr == NULL)
return -ENOMEM; goto out_free_rbps_virt;
he_dev->rbps_virt[i].virt = cpuaddr; he_dev->rbps_virt[i].virt = cpuaddr;
he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF); he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF);
@ -827,17 +831,21 @@ he_init_group(struct he_dev *he_dev, int group)
CONFIG_RBPL_BUFSIZE, 8, 0); CONFIG_RBPL_BUFSIZE, 8, 0);
if (he_dev->rbpl_pool == NULL) { if (he_dev->rbpl_pool == NULL) {
hprintk("unable to create rbpl pool\n"); hprintk("unable to create rbpl pool\n");
return -ENOMEM; goto out_free_rbps_virt;
} }
he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev, he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev,
CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys); CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys);
if (he_dev->rbpl_base == NULL) { if (he_dev->rbpl_base == NULL) {
hprintk("failed to alloc rbpl\n"); hprintk("failed to alloc rbpl_base\n");
return -ENOMEM; goto out_destroy_rbpl_pool;
} }
memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp)); memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp));
he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL); he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL);
if (he_dev->rbpl_virt == NULL) {
hprintk("failed to alloc rbpl_virt\n");
goto out_free_rbpl_base;
}
for (i = 0; i < CONFIG_RBPL_SIZE; ++i) { for (i = 0; i < CONFIG_RBPL_SIZE; ++i) {
dma_addr_t dma_handle; dma_addr_t dma_handle;
@ -845,7 +853,7 @@ he_init_group(struct he_dev *he_dev, int group)
cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &dma_handle); cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
if (cpuaddr == NULL) if (cpuaddr == NULL)
return -ENOMEM; goto out_free_rbpl_virt;
he_dev->rbpl_virt[i].virt = cpuaddr; he_dev->rbpl_virt[i].virt = cpuaddr;
he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF); he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF);
@ -870,7 +878,7 @@ he_init_group(struct he_dev *he_dev, int group)
CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys); CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys);
if (he_dev->rbrq_base == NULL) { if (he_dev->rbrq_base == NULL) {
hprintk("failed to allocate rbrq\n"); hprintk("failed to allocate rbrq\n");
return -ENOMEM; goto out_free_rbpl_virt;
} }
memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq)); memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq));
@ -894,7 +902,7 @@ he_init_group(struct he_dev *he_dev, int group)
CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys); CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys);
if (he_dev->tbrq_base == NULL) { if (he_dev->tbrq_base == NULL) {
hprintk("failed to allocate tbrq\n"); hprintk("failed to allocate tbrq\n");
return -ENOMEM; goto out_free_rbpq_base;
} }
memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq)); memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq));
@ -906,6 +914,39 @@ he_init_group(struct he_dev *he_dev, int group)
he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16)); he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16));
return 0; return 0;
out_free_rbpq_base:
pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE *
sizeof(struct he_rbrq), he_dev->rbrq_base,
he_dev->rbrq_phys);
i = CONFIG_RBPL_SIZE;
out_free_rbpl_virt:
while (--i)
pci_pool_free(he_dev->rbps_pool, he_dev->rbpl_virt[i].virt,
he_dev->rbps_base[i].phys);
kfree(he_dev->rbpl_virt);
out_free_rbpl_base:
pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE *
sizeof(struct he_rbp), he_dev->rbpl_base,
he_dev->rbpl_phys);
out_destroy_rbpl_pool:
pci_pool_destroy(he_dev->rbpl_pool);
i = CONFIG_RBPL_SIZE;
out_free_rbps_virt:
while (--i)
pci_pool_free(he_dev->rbpl_pool, he_dev->rbps_virt[i].virt,
he_dev->rbpl_base[i].phys);
kfree(he_dev->rbps_virt);
out_free_rbps_base:
pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE *
sizeof(struct he_rbp), he_dev->rbps_base,
he_dev->rbps_phys);
out_destroy_rbps_pool:
pci_pool_destroy(he_dev->rbps_pool);
return -ENOMEM;
} }
static int __devinit static int __devinit

View file

@ -25,6 +25,10 @@ SOLOS_ATTR_RO(RSCorrectedErrorsUp)
SOLOS_ATTR_RO(RSUnCorrectedErrorsUp) SOLOS_ATTR_RO(RSUnCorrectedErrorsUp)
SOLOS_ATTR_RO(InterleaveRDn) SOLOS_ATTR_RO(InterleaveRDn)
SOLOS_ATTR_RO(InterleaveRUp) SOLOS_ATTR_RO(InterleaveRUp)
SOLOS_ATTR_RO(BisRDn)
SOLOS_ATTR_RO(BisRUp)
SOLOS_ATTR_RO(INPdown)
SOLOS_ATTR_RO(INPup)
SOLOS_ATTR_RO(ShowtimeStart) SOLOS_ATTR_RO(ShowtimeStart)
SOLOS_ATTR_RO(ATURVendor) SOLOS_ATTR_RO(ATURVendor)
SOLOS_ATTR_RO(ATUCCountry) SOLOS_ATTR_RO(ATUCCountry)
@ -62,6 +66,13 @@ SOLOS_ATTR_RW(Defaults)
SOLOS_ATTR_RW(LineMode) SOLOS_ATTR_RW(LineMode)
SOLOS_ATTR_RW(Profile) SOLOS_ATTR_RW(Profile)
SOLOS_ATTR_RW(DetectNoise) SOLOS_ATTR_RW(DetectNoise)
SOLOS_ATTR_RW(BisAForceSNRMarginDn)
SOLOS_ATTR_RW(BisMForceSNRMarginDn)
SOLOS_ATTR_RW(BisAMaxMargin)
SOLOS_ATTR_RW(BisMMaxMargin)
SOLOS_ATTR_RW(AnnexAForceSNRMarginDn)
SOLOS_ATTR_RW(AnnexAMaxMargin)
SOLOS_ATTR_RW(AnnexMMaxMargin)
SOLOS_ATTR_RO(SupportedAnnexes) SOLOS_ATTR_RO(SupportedAnnexes)
SOLOS_ATTR_RO(Status) SOLOS_ATTR_RO(Status)
SOLOS_ATTR_RO(TotalStart) SOLOS_ATTR_RO(TotalStart)

View file

@ -59,21 +59,29 @@
#define RX_DMA_ADDR(port) (0x30 + (4 * (port))) #define RX_DMA_ADDR(port) (0x30 + (4 * (port)))
#define DATA_RAM_SIZE 32768 #define DATA_RAM_SIZE 32768
#define BUF_SIZE 4096 #define BUF_SIZE 2048
#define OLD_BUF_SIZE 4096 /* For FPGA versions <= 2*/
#define FPGA_PAGE 528 /* FPGA flash page size*/ #define FPGA_PAGE 528 /* FPGA flash page size*/
#define SOLOS_PAGE 512 /* Solos flash page size*/ #define SOLOS_PAGE 512 /* Solos flash page size*/
#define FPGA_BLOCK (FPGA_PAGE * 8) /* FPGA flash block size*/ #define FPGA_BLOCK (FPGA_PAGE * 8) /* FPGA flash block size*/
#define SOLOS_BLOCK (SOLOS_PAGE * 8) /* Solos flash block size*/ #define SOLOS_BLOCK (SOLOS_PAGE * 8) /* Solos flash block size*/
#define RX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2) #define RX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2)
#define TX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2 + BUF_SIZE) #define TX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2 + (card->buffer_size))
#define FLASH_BUF ((card->buffers) + 4*(card->buffer_size)*2)
#define RX_DMA_SIZE 2048 #define RX_DMA_SIZE 2048
#define FPGA_VERSION(a,b) (((a) << 8) + (b))
#define LEGACY_BUFFERS 2
#define DMA_SUPPORTED 4
static int reset = 0; static int reset = 0;
static int atmdebug = 0; static int atmdebug = 0;
static int firmware_upgrade = 0; static int firmware_upgrade = 0;
static int fpga_upgrade = 0; static int fpga_upgrade = 0;
static int db_firmware_upgrade = 0;
static int db_fpga_upgrade = 0;
struct pkt_hdr { struct pkt_hdr {
__le16 size; __le16 size;
@ -116,6 +124,8 @@ struct solos_card {
wait_queue_head_t param_wq; wait_queue_head_t param_wq;
wait_queue_head_t fw_wq; wait_queue_head_t fw_wq;
int using_dma; int using_dma;
int fpga_version;
int buffer_size;
}; };
@ -136,10 +146,14 @@ MODULE_PARM_DESC(reset, "Reset Solos chips on startup");
MODULE_PARM_DESC(atmdebug, "Print ATM data"); MODULE_PARM_DESC(atmdebug, "Print ATM data");
MODULE_PARM_DESC(firmware_upgrade, "Initiate Solos firmware upgrade"); MODULE_PARM_DESC(firmware_upgrade, "Initiate Solos firmware upgrade");
MODULE_PARM_DESC(fpga_upgrade, "Initiate FPGA upgrade"); MODULE_PARM_DESC(fpga_upgrade, "Initiate FPGA upgrade");
MODULE_PARM_DESC(db_firmware_upgrade, "Initiate daughter board Solos firmware upgrade");
MODULE_PARM_DESC(db_fpga_upgrade, "Initiate daughter board FPGA upgrade");
module_param(reset, int, 0444); module_param(reset, int, 0444);
module_param(atmdebug, int, 0644); module_param(atmdebug, int, 0644);
module_param(firmware_upgrade, int, 0444); module_param(firmware_upgrade, int, 0444);
module_param(fpga_upgrade, int, 0444); module_param(fpga_upgrade, int, 0444);
module_param(db_firmware_upgrade, int, 0444);
module_param(db_fpga_upgrade, int, 0444);
static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb, static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb,
struct atm_vcc *vcc); struct atm_vcc *vcc);
@ -517,10 +531,32 @@ static int flash_upgrade(struct solos_card *card, int chip)
if (chip == 0) { if (chip == 0) {
fw_name = "solos-FPGA.bin"; fw_name = "solos-FPGA.bin";
blocksize = FPGA_BLOCK; blocksize = FPGA_BLOCK;
} else { }
if (chip == 1) {
fw_name = "solos-Firmware.bin"; fw_name = "solos-Firmware.bin";
blocksize = SOLOS_BLOCK; blocksize = SOLOS_BLOCK;
} }
if (chip == 2){
if (card->fpga_version > LEGACY_BUFFERS){
fw_name = "solos-db-FPGA.bin";
blocksize = FPGA_BLOCK;
} else {
dev_info(&card->dev->dev, "FPGA version doesn't support daughter board upgrades\n");
return -EPERM;
}
}
if (chip == 3){
if (card->fpga_version > LEGACY_BUFFERS){
fw_name = "solos-Firmware.bin";
blocksize = SOLOS_BLOCK;
} else {
dev_info(&card->dev->dev, "FPGA version doesn't support daughter board upgrades\n");
return -EPERM;
}
}
if (request_firmware(&fw, fw_name, &card->dev->dev)) if (request_firmware(&fw, fw_name, &card->dev->dev))
return -ENOENT; return -ENOENT;
@ -536,8 +572,10 @@ static int flash_upgrade(struct solos_card *card, int chip)
data32 = ioread32(card->config_regs + FPGA_MODE); data32 = ioread32(card->config_regs + FPGA_MODE);
/* Set mode to Chip Erase */ /* Set mode to Chip Erase */
dev_info(&card->dev->dev, "Set FPGA Flash mode to %s Chip Erase\n", if(chip == 0 || chip == 2)
chip?"Solos":"FPGA"); dev_info(&card->dev->dev, "Set FPGA Flash mode to FPGA Chip Erase\n");
if(chip == 1 || chip == 3)
dev_info(&card->dev->dev, "Set FPGA Flash mode to Solos Chip Erase\n");
iowrite32((chip * 2), card->config_regs + FLASH_MODE); iowrite32((chip * 2), card->config_regs + FLASH_MODE);
@ -557,7 +595,10 @@ static int flash_upgrade(struct solos_card *card, int chip)
/* Copy block to buffer, swapping each 16 bits */ /* Copy block to buffer, swapping each 16 bits */
for(i = 0; i < blocksize; i += 4) { for(i = 0; i < blocksize; i += 4) {
uint32_t word = swahb32p((uint32_t *)(fw->data + offset + i)); uint32_t word = swahb32p((uint32_t *)(fw->data + offset + i));
iowrite32(word, RX_BUF(card, 3) + i); if(card->fpga_version > LEGACY_BUFFERS)
iowrite32(word, FLASH_BUF + i);
else
iowrite32(word, RX_BUF(card, 3) + i);
} }
/* Specify block number and then trigger flash write */ /* Specify block number and then trigger flash write */
@ -630,6 +671,10 @@ void solos_bh(unsigned long card_arg)
memcpy_fromio(header, RX_BUF(card, port), sizeof(*header)); memcpy_fromio(header, RX_BUF(card, port), sizeof(*header));
size = le16_to_cpu(header->size); size = le16_to_cpu(header->size);
if (size > (card->buffer_size - sizeof(*header))){
dev_warn(&card->dev->dev, "Invalid buffer size\n");
continue;
}
skb = alloc_skb(size + 1, GFP_ATOMIC); skb = alloc_skb(size + 1, GFP_ATOMIC);
if (!skb) { if (!skb) {
@ -1094,12 +1139,18 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
fpga_ver = (data32 & 0x0000FFFF); fpga_ver = (data32 & 0x0000FFFF);
major_ver = ((data32 & 0xFF000000) >> 24); major_ver = ((data32 & 0xFF000000) >> 24);
minor_ver = ((data32 & 0x00FF0000) >> 16); minor_ver = ((data32 & 0x00FF0000) >> 16);
card->fpga_version = FPGA_VERSION(major_ver,minor_ver);
if (card->fpga_version > LEGACY_BUFFERS)
card->buffer_size = BUF_SIZE;
else
card->buffer_size = OLD_BUF_SIZE;
dev_info(&dev->dev, "Solos FPGA Version %d.%02d svn-%d\n", dev_info(&dev->dev, "Solos FPGA Version %d.%02d svn-%d\n",
major_ver, minor_ver, fpga_ver); major_ver, minor_ver, fpga_ver);
if (0 && fpga_ver > 27) if (card->fpga_version >= DMA_SUPPORTED){
card->using_dma = 1; card->using_dma = 1;
else { } else {
card->using_dma = 0;
/* Set RX empty flag for all ports */ /* Set RX empty flag for all ports */
iowrite32(0xF0, card->config_regs + FLAGS_ADDR); iowrite32(0xF0, card->config_regs + FLAGS_ADDR);
} }
@ -1131,6 +1182,12 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
if (firmware_upgrade) if (firmware_upgrade)
flash_upgrade(card, 1); flash_upgrade(card, 1);
if (db_fpga_upgrade)
flash_upgrade(card, 2);
if (db_firmware_upgrade)
flash_upgrade(card, 3);
err = atm_init(card); err = atm_init(card);
if (err) if (err)
goto out_free_irq; goto out_free_irq;

View file

@ -813,10 +813,10 @@ static int vortex_suspend(struct pci_dev *pdev, pm_message_t state)
if (netif_running(dev)) { if (netif_running(dev)) {
netif_device_detach(dev); netif_device_detach(dev);
vortex_down(dev, 1); vortex_down(dev, 1);
disable_irq(dev->irq);
} }
pci_save_state(pdev); pci_save_state(pdev);
pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
free_irq(dev->irq, dev);
pci_disable_device(pdev); pci_disable_device(pdev);
pci_set_power_state(pdev, pci_choose_state(pdev, state)); pci_set_power_state(pdev, pci_choose_state(pdev, state));
} }
@ -839,18 +839,12 @@ static int vortex_resume(struct pci_dev *pdev)
return err; return err;
} }
pci_set_master(pdev); pci_set_master(pdev);
if (request_irq(dev->irq, vp->full_bus_master_rx ?
&boomerang_interrupt : &vortex_interrupt, IRQF_SHARED, dev->name, dev)) {
pr_warning("%s: Could not reserve IRQ %d\n", dev->name, dev->irq);
pci_disable_device(pdev);
return -EBUSY;
}
if (netif_running(dev)) { if (netif_running(dev)) {
err = vortex_up(dev); err = vortex_up(dev);
if (err) if (err)
return err; return err;
else enable_irq(dev->irq);
netif_device_attach(dev); netif_device_attach(dev);
} }
} }
return 0; return 0;

View file

@ -87,7 +87,7 @@
/* These identify the driver base version and may not be removed. */ /* These identify the driver base version and may not be removed. */
static char version[] = static char version[] =
KERN_INFO DRV_NAME ": 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n"; DRV_NAME ": 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n";
MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>"); MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>");
MODULE_DESCRIPTION("RealTek RTL-8139C+ series 10/100 PCI Ethernet driver"); MODULE_DESCRIPTION("RealTek RTL-8139C+ series 10/100 PCI Ethernet driver");

View file

@ -1875,7 +1875,7 @@ config 68360_ENET
config FEC config FEC
bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)" bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
depends on M523x || M527x || M5272 || M528x || M520x || M532x || MACH_MX27 || ARCH_MX35 depends on M523x || M527x || M5272 || M528x || M520x || M532x || MACH_MX27 || ARCH_MX35 || ARCH_MX25
help help
Say Y here if you want to use the built-in 10/100 Fast ethernet Say Y here if you want to use the built-in 10/100 Fast ethernet
controller on some Motorola ColdFire and Freescale i.MX processors. controller on some Motorola ColdFire and Freescale i.MX processors.

View file

@ -2296,7 +2296,7 @@ static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state)
u32 ctrl; u32 ctrl;
u32 mac_ctrl_data; u32 mac_ctrl_data;
u32 master_ctrl_data; u32 master_ctrl_data;
u32 wol_ctrl_data; u32 wol_ctrl_data = 0;
u16 mii_bmsr_data; u16 mii_bmsr_data;
u16 save_autoneg_advertised; u16 save_autoneg_advertised;
u16 mii_intr_status_data; u16 mii_intr_status_data;

View file

@ -75,6 +75,13 @@ config CAN_EMS_PCI
CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche
(http://www.ems-wuensche.de). (http://www.ems-wuensche.de).
config CAN_EMS_USB
tristate "EMS CPC-USB/ARM7 CAN/USB interface"
depends on USB && CAN_DEV
---help---
This driver is for the one channel CPC-USB/ARM7 CAN/USB interface
from from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de).
config CAN_KVASER_PCI config CAN_KVASER_PCI
tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards" tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards"
depends on PCI && CAN_SJA1000 depends on PCI && CAN_SJA1000
@ -82,6 +89,12 @@ config CAN_KVASER_PCI
This driver is for the the PCIcanx and PCIcan cards (1, 2 or This driver is for the the PCIcanx and PCIcan cards (1, 2 or
4 channel) from Kvaser (http://www.kvaser.com). 4 channel) from Kvaser (http://www.kvaser.com).
config CAN_AT91
tristate "Atmel AT91 onchip CAN controller"
depends on CAN && CAN_DEV && ARCH_AT91SAM9263
---help---
This is a driver for the SoC CAN controller in Atmel's AT91SAM9263.
config CAN_DEBUG_DEVICES config CAN_DEBUG_DEVICES
bool "CAN devices debugging messages" bool "CAN devices debugging messages"
depends on CAN depends on CAN

View file

@ -7,6 +7,9 @@ obj-$(CONFIG_CAN_VCAN) += vcan.o
obj-$(CONFIG_CAN_DEV) += can-dev.o obj-$(CONFIG_CAN_DEV) += can-dev.o
can-dev-y := dev.o can-dev-y := dev.o
obj-y += usb/
obj-$(CONFIG_CAN_SJA1000) += sja1000/ obj-$(CONFIG_CAN_SJA1000) += sja1000/
obj-$(CONFIG_CAN_AT91) += at91_can.o
ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG

View file

@ -94,12 +94,14 @@ struct ems_pci_card {
#define EMS_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK) #define EMS_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK)
#define EMS_PCI_V1_BASE_BAR 1 #define EMS_PCI_V1_BASE_BAR 1
#define EMS_PCI_V1_MEM_SIZE 4096 #define EMS_PCI_V1_CONF_SIZE 4096 /* size of PITA control area */
#define EMS_PCI_V2_BASE_BAR 2 #define EMS_PCI_V2_BASE_BAR 2
#define EMS_PCI_V2_MEM_SIZE 128 #define EMS_PCI_V2_CONF_SIZE 128 /* size of PLX control area */
#define EMS_PCI_CAN_BASE_OFFSET 0x400 /* offset where the controllers starts */ #define EMS_PCI_CAN_BASE_OFFSET 0x400 /* offset where the controllers starts */
#define EMS_PCI_CAN_CTRL_SIZE 0x200 /* memory size for each controller */ #define EMS_PCI_CAN_CTRL_SIZE 0x200 /* memory size for each controller */
#define EMS_PCI_BASE_SIZE 4096 /* size of controller area */
static struct pci_device_id ems_pci_tbl[] = { static struct pci_device_id ems_pci_tbl[] = {
/* CPC-PCI v1 */ /* CPC-PCI v1 */
{PCI_VENDOR_ID_SIEMENS, 0x2104, PCI_ANY_ID, PCI_ANY_ID,}, {PCI_VENDOR_ID_SIEMENS, 0x2104, PCI_ANY_ID, PCI_ANY_ID,},
@ -224,7 +226,7 @@ static int __devinit ems_pci_add_card(struct pci_dev *pdev,
struct sja1000_priv *priv; struct sja1000_priv *priv;
struct net_device *dev; struct net_device *dev;
struct ems_pci_card *card; struct ems_pci_card *card;
int max_chan, mem_size, base_bar; int max_chan, conf_size, base_bar;
int err, i; int err, i;
/* Enabling PCI device */ /* Enabling PCI device */
@ -251,22 +253,22 @@ static int __devinit ems_pci_add_card(struct pci_dev *pdev,
card->version = 2; /* CPC-PCI v2 */ card->version = 2; /* CPC-PCI v2 */
max_chan = EMS_PCI_V2_MAX_CHAN; max_chan = EMS_PCI_V2_MAX_CHAN;
base_bar = EMS_PCI_V2_BASE_BAR; base_bar = EMS_PCI_V2_BASE_BAR;
mem_size = EMS_PCI_V2_MEM_SIZE; conf_size = EMS_PCI_V2_CONF_SIZE;
} else { } else {
card->version = 1; /* CPC-PCI v1 */ card->version = 1; /* CPC-PCI v1 */
max_chan = EMS_PCI_V1_MAX_CHAN; max_chan = EMS_PCI_V1_MAX_CHAN;
base_bar = EMS_PCI_V1_BASE_BAR; base_bar = EMS_PCI_V1_BASE_BAR;
mem_size = EMS_PCI_V1_MEM_SIZE; conf_size = EMS_PCI_V1_CONF_SIZE;
} }
/* Remap configuration space and controller memory area */ /* Remap configuration space and controller memory area */
card->conf_addr = pci_iomap(pdev, 0, mem_size); card->conf_addr = pci_iomap(pdev, 0, conf_size);
if (card->conf_addr == NULL) { if (card->conf_addr == NULL) {
err = -ENOMEM; err = -ENOMEM;
goto failure_cleanup; goto failure_cleanup;
} }
card->base_addr = pci_iomap(pdev, base_bar, mem_size); card->base_addr = pci_iomap(pdev, base_bar, EMS_PCI_BASE_SIZE);
if (card->base_addr == NULL) { if (card->base_addr == NULL) {
err = -ENOMEM; err = -ENOMEM;
goto failure_cleanup; goto failure_cleanup;

View file

@ -0,0 +1,5 @@
#
# Makefile for the Linux Controller Area Network USB drivers.
#
obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o

File diff suppressed because it is too large Load diff

View file

@ -85,8 +85,6 @@ static int cnic_uio_open(struct uio_info *uinfo, struct inode *inode)
cp->uio_dev = iminor(inode); cp->uio_dev = iminor(inode);
cnic_shutdown_bnx2_rx_ring(dev);
cnic_init_bnx2_tx_ring(dev); cnic_init_bnx2_tx_ring(dev);
cnic_init_bnx2_rx_ring(dev); cnic_init_bnx2_rx_ring(dev);
@ -98,6 +96,8 @@ static int cnic_uio_close(struct uio_info *uinfo, struct inode *inode)
struct cnic_dev *dev = uinfo->priv; struct cnic_dev *dev = uinfo->priv;
struct cnic_local *cp = dev->cnic_priv; struct cnic_local *cp = dev->cnic_priv;
cnic_shutdown_bnx2_rx_ring(dev);
cp->uio_dev = -1; cp->uio_dev = -1;
return 0; return 0;
} }

View file

@ -1109,7 +1109,7 @@ static int external_switch;
static int __devinit cpmac_probe(struct platform_device *pdev) static int __devinit cpmac_probe(struct platform_device *pdev)
{ {
int rc, phy_id; int rc, phy_id;
char mdio_bus_id[BUS_ID_SIZE]; char mdio_bus_id[MII_BUS_ID_SIZE];
struct resource *mem; struct resource *mem;
struct cpmac_priv *priv; struct cpmac_priv *priv;
struct net_device *dev; struct net_device *dev;
@ -1118,7 +1118,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
pdata = pdev->dev.platform_data; pdata = pdev->dev.platform_data;
if (external_switch || dumb_switch) { if (external_switch || dumb_switch) {
strncpy(mdio_bus_id, "0", BUS_ID_SIZE); /* fixed phys bus */ strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); /* fixed phys bus */
phy_id = pdev->id; phy_id = pdev->id;
} else { } else {
for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) { for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
@ -1126,7 +1126,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
continue; continue;
if (!cpmac_mii->phy_map[phy_id]) if (!cpmac_mii->phy_map[phy_id])
continue; continue;
strncpy(mdio_bus_id, cpmac_mii->id, BUS_ID_SIZE); strncpy(mdio_bus_id, cpmac_mii->id, MII_BUS_ID_SIZE);
break; break;
} }
} }
@ -1167,7 +1167,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
priv->msg_enable = netif_msg_init(debug_level, 0xff); priv->msg_enable = netif_msg_init(debug_level, 0xff);
memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr)); memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr));
snprintf(priv->phy_name, BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id); snprintf(priv->phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0, priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0,
PHY_INTERFACE_MODE_MII); PHY_INTERFACE_MODE_MII);

View file

@ -3083,7 +3083,6 @@ static const struct net_device_ops ehea_netdev_ops = {
.ndo_poll_controller = ehea_netpoll, .ndo_poll_controller = ehea_netpoll,
#endif #endif
.ndo_get_stats = ehea_get_stats, .ndo_get_stats = ehea_get_stats,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = ehea_set_mac_addr, .ndo_set_mac_address = ehea_set_mac_addr,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
.ndo_set_multicast_list = ehea_set_multicast_list, .ndo_set_multicast_list = ehea_set_multicast_list,

View file

@ -285,41 +285,6 @@ void igb_mta_set(struct e1000_hw *hw, u32 hash_value)
wrfl(); wrfl();
} }
/**
* igb_update_mc_addr_list - Update Multicast addresses
* @hw: pointer to the HW structure
* @mc_addr_list: array of multicast addresses to program
* @mc_addr_count: number of multicast addresses to program
*
* Updates entire Multicast Table Array.
* The caller must have a packed mc_addr_list of multicast addresses.
**/
void igb_update_mc_addr_list(struct e1000_hw *hw,
u8 *mc_addr_list, u32 mc_addr_count)
{
u32 hash_value, hash_bit, hash_reg;
int i;
/* clear mta_shadow */
memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
/* update mta_shadow from mc_addr_list */
for (i = 0; (u32) i < mc_addr_count; i++) {
hash_value = igb_hash_mc_addr(hw, mc_addr_list);
hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
hash_bit = hash_value & 0x1F;
hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit);
mc_addr_list += (ETH_ALEN);
}
/* replace the entire MTA table */
for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
array_wr32(E1000_MTA, i, hw->mac.mta_shadow[i]);
wrfl();
}
/** /**
* igb_hash_mc_addr - Generate a multicast hash value * igb_hash_mc_addr - Generate a multicast hash value
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
@ -329,7 +294,7 @@ void igb_update_mc_addr_list(struct e1000_hw *hw,
* the multicast filter table array address and new table value. See * the multicast filter table array address and new table value. See
* igb_mta_set() * igb_mta_set()
**/ **/
u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) static u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
{ {
u32 hash_value, hash_mask; u32 hash_value, hash_mask;
u8 bit_shift = 0; u8 bit_shift = 0;
@ -391,6 +356,41 @@ u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
return hash_value; return hash_value;
} }
/**
* igb_update_mc_addr_list - Update Multicast addresses
* @hw: pointer to the HW structure
* @mc_addr_list: array of multicast addresses to program
* @mc_addr_count: number of multicast addresses to program
*
* Updates entire Multicast Table Array.
* The caller must have a packed mc_addr_list of multicast addresses.
**/
void igb_update_mc_addr_list(struct e1000_hw *hw,
u8 *mc_addr_list, u32 mc_addr_count)
{
u32 hash_value, hash_bit, hash_reg;
int i;
/* clear mta_shadow */
memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
/* update mta_shadow from mc_addr_list */
for (i = 0; (u32) i < mc_addr_count; i++) {
hash_value = igb_hash_mc_addr(hw, mc_addr_list);
hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
hash_bit = hash_value & 0x1F;
hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit);
mc_addr_list += (ETH_ALEN);
}
/* replace the entire MTA table */
for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
array_wr32(E1000_MTA, i, hw->mac.mta_shadow[i]);
wrfl();
}
/** /**
* igb_clear_hw_cntrs_base - Clear base hardware counters * igb_clear_hw_cntrs_base - Clear base hardware counters
* @hw: pointer to the HW structure * @hw: pointer to the HW structure

View file

@ -88,6 +88,5 @@ enum e1000_mng_mode {
#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2 #define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2
extern void e1000_init_function_pointers_82575(struct e1000_hw *hw); extern void e1000_init_function_pointers_82575(struct e1000_hw *hw);
extern u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr);
#endif #endif

View file

@ -267,7 +267,8 @@ struct ixgbe_adapter {
enum ixgbe_fc_mode last_lfc_mode; enum ixgbe_fc_mode last_lfc_mode;
/* Interrupt Throttle Rate */ /* Interrupt Throttle Rate */
u32 itr_setting; u32 rx_itr_setting;
u32 tx_itr_setting;
u16 eitr_low; u16 eitr_low;
u16 eitr_high; u16 eitr_high;
@ -351,7 +352,8 @@ struct ixgbe_adapter {
struct ixgbe_hw_stats stats; struct ixgbe_hw_stats stats;
/* Interrupt Throttle Rate */ /* Interrupt Throttle Rate */
u32 eitr_param; u32 rx_eitr_param;
u32 tx_eitr_param;
unsigned long state; unsigned long state;
u64 tx_busy; u64 tx_busy;

View file

@ -1929,7 +1929,7 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
ec->tx_max_coalesced_frames_irq = adapter->tx_ring[0].work_limit; ec->tx_max_coalesced_frames_irq = adapter->tx_ring[0].work_limit;
/* only valid if in constant ITR mode */ /* only valid if in constant ITR mode */
switch (adapter->itr_setting) { switch (adapter->rx_itr_setting) {
case 0: case 0:
/* throttling disabled */ /* throttling disabled */
ec->rx_coalesce_usecs = 0; ec->rx_coalesce_usecs = 0;
@ -1940,9 +1940,25 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
break; break;
default: default:
/* fixed interrupt rate mode */ /* fixed interrupt rate mode */
ec->rx_coalesce_usecs = 1000000/adapter->eitr_param; ec->rx_coalesce_usecs = 1000000/adapter->rx_eitr_param;
break; break;
} }
/* only valid if in constant ITR mode */
switch (adapter->tx_itr_setting) {
case 0:
/* throttling disabled */
ec->tx_coalesce_usecs = 0;
break;
case 1:
/* dynamic ITR mode */
ec->tx_coalesce_usecs = 1;
break;
default:
ec->tx_coalesce_usecs = 1000000/adapter->tx_eitr_param;
break;
}
return 0; return 0;
} }
@ -1953,6 +1969,14 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
struct ixgbe_q_vector *q_vector; struct ixgbe_q_vector *q_vector;
int i; int i;
/*
* don't accept tx specific changes if we've got mixed RxTx vectors
* test and jump out here if needed before changing the rx numbers
*/
if ((1000000/ec->tx_coalesce_usecs) != adapter->tx_eitr_param &&
adapter->q_vector[0]->txr_count && adapter->q_vector[0]->rxr_count)
return -EINVAL;
if (ec->tx_max_coalesced_frames_irq) if (ec->tx_max_coalesced_frames_irq)
adapter->tx_ring[0].work_limit = ec->tx_max_coalesced_frames_irq; adapter->tx_ring[0].work_limit = ec->tx_max_coalesced_frames_irq;
@ -1963,26 +1987,49 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
return -EINVAL; return -EINVAL;
/* store the value in ints/second */ /* store the value in ints/second */
adapter->eitr_param = 1000000/ec->rx_coalesce_usecs; adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs;
/* static value of interrupt rate */ /* static value of interrupt rate */
adapter->itr_setting = adapter->eitr_param; adapter->rx_itr_setting = adapter->rx_eitr_param;
/* clear the lower bit as its used for dynamic state */ /* clear the lower bit as its used for dynamic state */
adapter->itr_setting &= ~1; adapter->rx_itr_setting &= ~1;
} else if (ec->rx_coalesce_usecs == 1) { } else if (ec->rx_coalesce_usecs == 1) {
/* 1 means dynamic mode */ /* 1 means dynamic mode */
adapter->eitr_param = 20000; adapter->rx_eitr_param = 20000;
adapter->itr_setting = 1; adapter->rx_itr_setting = 1;
} else { } else {
/* /*
* any other value means disable eitr, which is best * any other value means disable eitr, which is best
* served by setting the interrupt rate very high * served by setting the interrupt rate very high
*/ */
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
adapter->eitr_param = IXGBE_MAX_RSC_INT_RATE; adapter->rx_eitr_param = IXGBE_MAX_RSC_INT_RATE;
else else
adapter->eitr_param = IXGBE_MAX_INT_RATE; adapter->rx_eitr_param = IXGBE_MAX_INT_RATE;
adapter->itr_setting = 0; adapter->rx_itr_setting = 0;
}
if (ec->tx_coalesce_usecs > 1) {
/* check the limits */
if ((1000000/ec->tx_coalesce_usecs > IXGBE_MAX_INT_RATE) ||
(1000000/ec->tx_coalesce_usecs < IXGBE_MIN_INT_RATE))
return -EINVAL;
/* store the value in ints/second */
adapter->tx_eitr_param = 1000000/ec->tx_coalesce_usecs;
/* static value of interrupt rate */
adapter->tx_itr_setting = adapter->tx_eitr_param;
/* clear the lower bit as its used for dynamic state */
adapter->tx_itr_setting &= ~1;
} else if (ec->tx_coalesce_usecs == 1) {
/* 1 means dynamic mode */
adapter->tx_eitr_param = 10000;
adapter->tx_itr_setting = 1;
} else {
adapter->tx_eitr_param = IXGBE_MAX_INT_RATE;
adapter->tx_itr_setting = 0;
} }
/* MSI/MSIx Interrupt Mode */ /* MSI/MSIx Interrupt Mode */
@ -1992,17 +2039,17 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
for (i = 0; i < num_vectors; i++) { for (i = 0; i < num_vectors; i++) {
q_vector = adapter->q_vector[i]; q_vector = adapter->q_vector[i];
if (q_vector->txr_count && !q_vector->rxr_count) if (q_vector->txr_count && !q_vector->rxr_count)
/* tx vector gets half the rate */ /* tx only */
q_vector->eitr = (adapter->eitr_param >> 1); q_vector->eitr = adapter->tx_eitr_param;
else else
/* rx only or mixed */ /* rx only or mixed */
q_vector->eitr = adapter->eitr_param; q_vector->eitr = adapter->rx_eitr_param;
ixgbe_write_eitr(q_vector); ixgbe_write_eitr(q_vector);
} }
/* Legacy Interrupt Mode */ /* Legacy Interrupt Mode */
} else { } else {
q_vector = adapter->q_vector[0]; q_vector = adapter->q_vector[0];
q_vector->eitr = adapter->eitr_param; q_vector->eitr = adapter->rx_eitr_param;
ixgbe_write_eitr(q_vector); ixgbe_write_eitr(q_vector);
} }

View file

@ -926,12 +926,12 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
r_idx + 1); r_idx + 1);
} }
/* if this is a tx only vector halve the interrupt rate */
if (q_vector->txr_count && !q_vector->rxr_count) if (q_vector->txr_count && !q_vector->rxr_count)
q_vector->eitr = (adapter->eitr_param >> 1); /* tx only */
q_vector->eitr = adapter->tx_eitr_param;
else if (q_vector->rxr_count) else if (q_vector->rxr_count)
/* rx only */ /* rx or mixed */
q_vector->eitr = adapter->eitr_param; q_vector->eitr = adapter->rx_eitr_param;
ixgbe_write_eitr(q_vector); ixgbe_write_eitr(q_vector);
} }
@ -1359,7 +1359,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
/* If all Rx work done, exit the polling mode */ /* If all Rx work done, exit the polling mode */
if (work_done < budget) { if (work_done < budget) {
napi_complete(napi); napi_complete(napi);
if (adapter->itr_setting & 1) if (adapter->rx_itr_setting & 1)
ixgbe_set_itr_msix(q_vector); ixgbe_set_itr_msix(q_vector);
if (!test_bit(__IXGBE_DOWN, &adapter->state)) if (!test_bit(__IXGBE_DOWN, &adapter->state))
ixgbe_irq_enable_queues(adapter, ixgbe_irq_enable_queues(adapter,
@ -1420,7 +1420,7 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget)
/* If all Rx work done, exit the polling mode */ /* If all Rx work done, exit the polling mode */
if (work_done < budget) { if (work_done < budget) {
napi_complete(napi); napi_complete(napi);
if (adapter->itr_setting & 1) if (adapter->rx_itr_setting & 1)
ixgbe_set_itr_msix(q_vector); ixgbe_set_itr_msix(q_vector);
if (!test_bit(__IXGBE_DOWN, &adapter->state)) if (!test_bit(__IXGBE_DOWN, &adapter->state))
ixgbe_irq_enable_queues(adapter, ixgbe_irq_enable_queues(adapter,
@ -1458,10 +1458,10 @@ static int ixgbe_clean_txonly(struct napi_struct *napi, int budget)
if (!ixgbe_clean_tx_irq(q_vector, tx_ring)) if (!ixgbe_clean_tx_irq(q_vector, tx_ring))
work_done = budget; work_done = budget;
/* If all Rx work done, exit the polling mode */ /* If all Tx work done, exit the polling mode */
if (work_done < budget) { if (work_done < budget) {
napi_complete(napi); napi_complete(napi);
if (adapter->itr_setting & 1) if (adapter->tx_itr_setting & 1)
ixgbe_set_itr_msix(q_vector); ixgbe_set_itr_msix(q_vector);
if (!test_bit(__IXGBE_DOWN, &adapter->state)) if (!test_bit(__IXGBE_DOWN, &adapter->state))
ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx)); ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx));
@ -1848,7 +1848,7 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter)
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
IXGBE_WRITE_REG(hw, IXGBE_EITR(0), IXGBE_WRITE_REG(hw, IXGBE_EITR(0),
EITR_INTS_PER_SEC_TO_REG(adapter->eitr_param)); EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr_param));
ixgbe_set_ivar(adapter, 0, 0, 0); ixgbe_set_ivar(adapter, 0, 0, 0);
ixgbe_set_ivar(adapter, 1, 0, 0); ixgbe_set_ivar(adapter, 1, 0, 0);
@ -1969,6 +1969,50 @@ static u32 ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
return mrqc; return mrqc;
} }
/**
* ixgbe_configure_rscctl - enable RSC for the indicated ring
* @adapter: address of board private structure
* @index: index of ring to set
* @rx_buf_len: rx buffer length
**/
static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, int index,
int rx_buf_len)
{
struct ixgbe_ring *rx_ring;
struct ixgbe_hw *hw = &adapter->hw;
int j;
u32 rscctrl;
rx_ring = &adapter->rx_ring[index];
j = rx_ring->reg_idx;
rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(j));
rscctrl |= IXGBE_RSCCTL_RSCEN;
/*
* we must limit the number of descriptors so that the
* total size of max desc * buf_len is not greater
* than 65535
*/
if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
#if (MAX_SKB_FRAGS > 16)
rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
#elif (MAX_SKB_FRAGS > 8)
rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
#elif (MAX_SKB_FRAGS > 4)
rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
#else
rscctrl |= IXGBE_RSCCTL_MAXDESC_1;
#endif
} else {
if (rx_buf_len < IXGBE_RXBUFFER_4096)
rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
else if (rx_buf_len < IXGBE_RXBUFFER_8192)
rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
else
rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
}
IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(j), rscctrl);
}
/** /**
* ixgbe_configure_rx - Configure 8259x Receive Unit after Reset * ixgbe_configure_rx - Configure 8259x Receive Unit after Reset
* @adapter: board private structure * @adapter: board private structure
@ -1990,7 +2034,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
u32 fctrl, hlreg0; u32 fctrl, hlreg0;
u32 reta = 0, mrqc = 0; u32 reta = 0, mrqc = 0;
u32 rdrxctl; u32 rdrxctl;
u32 rscctrl;
int rx_buf_len; int rx_buf_len;
/* Decide whether to use packet split mode or not */ /* Decide whether to use packet split mode or not */
@ -2148,36 +2191,9 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) { if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
/* Enable 82599 HW-RSC */ /* Enable 82599 HW-RSC */
for (i = 0; i < adapter->num_rx_queues; i++) { for (i = 0; i < adapter->num_rx_queues; i++)
rx_ring = &adapter->rx_ring[i]; ixgbe_configure_rscctl(adapter, i, rx_buf_len);
j = rx_ring->reg_idx;
rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(j));
rscctrl |= IXGBE_RSCCTL_RSCEN;
/*
* we must limit the number of descriptors so that the
* total size of max desc * buf_len is not greater
* than 65535
*/
if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
#if (MAX_SKB_FRAGS > 16)
rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
#elif (MAX_SKB_FRAGS > 8)
rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
#elif (MAX_SKB_FRAGS > 4)
rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
#else
rscctrl |= IXGBE_RSCCTL_MAXDESC_1;
#endif
} else {
if (rx_buf_len < IXGBE_RXBUFFER_4096)
rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
else if (rx_buf_len < IXGBE_RXBUFFER_8192)
rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
else
rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
}
IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(j), rscctrl);
}
/* Disable RSC for ACK packets */ /* Disable RSC for ACK packets */
IXGBE_WRITE_REG(hw, IXGBE_RSCDBU, IXGBE_WRITE_REG(hw, IXGBE_RSCDBU,
(IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU))); (IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU)));
@ -2926,6 +2942,8 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
ixgbe_napi_disable_all(adapter); ixgbe_napi_disable_all(adapter);
clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
del_timer_sync(&adapter->sfp_timer);
del_timer_sync(&adapter->watchdog_timer); del_timer_sync(&adapter->watchdog_timer);
cancel_work_sync(&adapter->watchdog_task); cancel_work_sync(&adapter->watchdog_task);
@ -2989,7 +3007,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget)
/* If budget not fully consumed, exit the polling mode */ /* If budget not fully consumed, exit the polling mode */
if (work_done < budget) { if (work_done < budget) {
napi_complete(napi); napi_complete(napi);
if (adapter->itr_setting & 1) if (adapter->rx_itr_setting & 1)
ixgbe_set_itr(adapter); ixgbe_set_itr(adapter);
if (!test_bit(__IXGBE_DOWN, &adapter->state)) if (!test_bit(__IXGBE_DOWN, &adapter->state))
ixgbe_irq_enable_queues(adapter, IXGBE_EIMS_RTX_QUEUE); ixgbe_irq_enable_queues(adapter, IXGBE_EIMS_RTX_QUEUE);
@ -3599,7 +3617,10 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
if (!q_vector) if (!q_vector)
goto err_out; goto err_out;
q_vector->adapter = adapter; q_vector->adapter = adapter;
q_vector->eitr = adapter->eitr_param; if (q_vector->txr_count && !q_vector->rxr_count)
q_vector->eitr = adapter->tx_eitr_param;
else
q_vector->eitr = adapter->rx_eitr_param;
q_vector->v_idx = q_idx; q_vector->v_idx = q_idx;
netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64); netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64);
adapter->q_vector[q_idx] = q_vector; adapter->q_vector[q_idx] = q_vector;
@ -3868,8 +3889,10 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
hw->fc.disable_fc_autoneg = false; hw->fc.disable_fc_autoneg = false;
/* enable itr by default in dynamic mode */ /* enable itr by default in dynamic mode */
adapter->itr_setting = 1; adapter->rx_itr_setting = 1;
adapter->eitr_param = 20000; adapter->rx_eitr_param = 20000;
adapter->tx_itr_setting = 1;
adapter->tx_eitr_param = 10000;
/* set defaults for eitr in MegaBytes */ /* set defaults for eitr in MegaBytes */
adapter->eitr_low = 10; adapter->eitr_low = 10;

View file

@ -1469,6 +1469,7 @@ netxen_nic_resume(struct pci_dev *pdev)
} }
netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY); netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY);
return 0;
err_out_detach: err_out_detach:
netxen_nic_detach(adapter); netxen_nic_detach(adapter);
@ -1903,12 +1904,13 @@ static void netxen_tx_timeout_task(struct work_struct *work)
netif_wake_queue(adapter->netdev); netif_wake_queue(adapter->netdev);
goto done; clear_bit(__NX_RESETTING, &adapter->state);
} else { } else {
clear_bit(__NX_RESETTING, &adapter->state);
if (!netxen_nic_reset_context(adapter)) { if (!netxen_nic_reset_context(adapter)) {
adapter->netdev->trans_start = jiffies; adapter->netdev->trans_start = jiffies;
goto done; return;
} }
/* context reset failed, fall through for fw reset */ /* context reset failed, fall through for fw reset */
@ -1916,8 +1918,6 @@ static void netxen_tx_timeout_task(struct work_struct *work)
request_reset: request_reset:
adapter->need_fw_reset = 1; adapter->need_fw_reset = 1;
done:
clear_bit(__NX_RESETTING, &adapter->state);
} }
struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)

View file

@ -340,12 +340,11 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link)
base = &virt[hw_info[i].offset & (req.Size-1)]; base = &virt[hw_info[i].offset & (req.Size-1)];
if ((readb(base+0) == hw_info[i].a0) && if ((readb(base+0) == hw_info[i].a0) &&
(readb(base+2) == hw_info[i].a1) && (readb(base+2) == hw_info[i].a1) &&
(readb(base+4) == hw_info[i].a2)) (readb(base+4) == hw_info[i].a2)) {
break; for (j = 0; j < 6; j++)
} dev->dev_addr[j] = readb(base + (j<<1));
if (i < NR_INFO) { break;
for (j = 0; j < 6; j++) }
dev->dev_addr[j] = readb(base + (j<<1));
} }
iounmap(virt); iounmap(virt);

View file

@ -1497,7 +1497,6 @@ static int sky2_up(struct net_device *dev)
if (ramsize > 0) { if (ramsize > 0) {
u32 rxspace; u32 rxspace;
hw->flags |= SKY2_HW_RAM_BUFFER;
pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize); pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize);
if (ramsize < 16) if (ramsize < 16)
rxspace = ramsize / 2; rxspace = ramsize / 2;
@ -2926,6 +2925,9 @@ static int __devinit sky2_init(struct sky2_hw *hw)
++hw->ports; ++hw->ports;
} }
if (sky2_read8(hw, B2_E_0))
hw->flags |= SKY2_HW_RAM_BUFFER;
return 0; return 0;
} }

View file

@ -1016,7 +1016,6 @@ static const struct net_device_ops vnet_ops = {
.ndo_open = vnet_open, .ndo_open = vnet_open,
.ndo_stop = vnet_close, .ndo_stop = vnet_close,
.ndo_set_multicast_list = vnet_set_rx_mode, .ndo_set_multicast_list = vnet_set_rx_mode,
.ndo_change_mtu = eth_change_mtu,
.ndo_set_mac_address = vnet_set_mac_addr, .ndo_set_mac_address = vnet_set_mac_addr,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
.ndo_tx_timeout = vnet_tx_timeout, .ndo_tx_timeout = vnet_tx_timeout,

View file

@ -946,8 +946,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
char *name; char *name;
unsigned long flags = 0; unsigned long flags = 0;
err = -EINVAL;
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
err = security_tun_dev_create(); err = security_tun_dev_create();
@ -964,7 +962,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
flags |= TUN_TAP_DEV; flags |= TUN_TAP_DEV;
name = "tap%d"; name = "tap%d";
} else } else
goto failed; return -EINVAL;
if (*ifr->ifr_name) if (*ifr->ifr_name)
name = ifr->ifr_name; name = ifr->ifr_name;

View file

@ -263,6 +263,7 @@ static int kaweth_control(struct kaweth_device *kaweth,
int timeout) int timeout)
{ {
struct usb_ctrlrequest *dr; struct usb_ctrlrequest *dr;
int retval;
dbg("kaweth_control()"); dbg("kaweth_control()");
@ -278,18 +279,21 @@ static int kaweth_control(struct kaweth_device *kaweth,
return -ENOMEM; return -ENOMEM;
} }
dr->bRequestType= requesttype; dr->bRequestType = requesttype;
dr->bRequest = request; dr->bRequest = request;
dr->wValue = cpu_to_le16(value); dr->wValue = cpu_to_le16(value);
dr->wIndex = cpu_to_le16(index); dr->wIndex = cpu_to_le16(index);
dr->wLength = cpu_to_le16(size); dr->wLength = cpu_to_le16(size);
return kaweth_internal_control_msg(kaweth->dev, retval = kaweth_internal_control_msg(kaweth->dev,
pipe, pipe,
dr, dr,
data, data,
size, size,
timeout); timeout);
kfree(dr);
return retval;
} }
/**************************************************************** /****************************************************************

View file

@ -1227,7 +1227,7 @@ static const struct driver_info smsc95xx_info = {
.rx_fixup = smsc95xx_rx_fixup, .rx_fixup = smsc95xx_rx_fixup,
.tx_fixup = smsc95xx_tx_fixup, .tx_fixup = smsc95xx_tx_fixup,
.status = smsc95xx_status, .status = smsc95xx_status,
.flags = FLAG_ETHER, .flags = FLAG_ETHER | FLAG_SEND_ZLP,
}; };
static const struct usb_device_id products[] = { static const struct usb_device_id products[] = {
@ -1236,11 +1236,76 @@ static const struct usb_device_id products[] = {
USB_DEVICE(0x0424, 0x9500), USB_DEVICE(0x0424, 0x9500),
.driver_info = (unsigned long) &smsc95xx_info, .driver_info = (unsigned long) &smsc95xx_info,
}, },
{
/* SMSC9505 USB Ethernet Device */
USB_DEVICE(0x0424, 0x9505),
.driver_info = (unsigned long) &smsc95xx_info,
},
{
/* SMSC9500A USB Ethernet Device */
USB_DEVICE(0x0424, 0x9E00),
.driver_info = (unsigned long) &smsc95xx_info,
},
{
/* SMSC9505A USB Ethernet Device */
USB_DEVICE(0x0424, 0x9E01),
.driver_info = (unsigned long) &smsc95xx_info,
},
{ {
/* SMSC9512/9514 USB Hub & Ethernet Device */ /* SMSC9512/9514 USB Hub & Ethernet Device */
USB_DEVICE(0x0424, 0xec00), USB_DEVICE(0x0424, 0xec00),
.driver_info = (unsigned long) &smsc95xx_info, .driver_info = (unsigned long) &smsc95xx_info,
}, },
{
/* SMSC9500 USB Ethernet Device (SAL10) */
USB_DEVICE(0x0424, 0x9900),
.driver_info = (unsigned long) &smsc95xx_info,
},
{
/* SMSC9505 USB Ethernet Device (SAL10) */
USB_DEVICE(0x0424, 0x9901),
.driver_info = (unsigned long) &smsc95xx_info,
},
{
/* SMSC9500A USB Ethernet Device (SAL10) */
USB_DEVICE(0x0424, 0x9902),
.driver_info = (unsigned long) &smsc95xx_info,
},
{
/* SMSC9505A USB Ethernet Device (SAL10) */
USB_DEVICE(0x0424, 0x9903),
.driver_info = (unsigned long) &smsc95xx_info,
},
{
/* SMSC9512/9514 USB Hub & Ethernet Device (SAL10) */
USB_DEVICE(0x0424, 0x9904),
.driver_info = (unsigned long) &smsc95xx_info,
},
{
/* SMSC9500A USB Ethernet Device (HAL) */
USB_DEVICE(0x0424, 0x9905),
.driver_info = (unsigned long) &smsc95xx_info,
},
{
/* SMSC9505A USB Ethernet Device (HAL) */
USB_DEVICE(0x0424, 0x9906),
.driver_info = (unsigned long) &smsc95xx_info,
},
{
/* SMSC9500 USB Ethernet Device (Alternate ID) */
USB_DEVICE(0x0424, 0x9907),
.driver_info = (unsigned long) &smsc95xx_info,
},
{
/* SMSC9500A USB Ethernet Device (Alternate ID) */
USB_DEVICE(0x0424, 0x9908),
.driver_info = (unsigned long) &smsc95xx_info,
},
{
/* SMSC9512/9514 USB Hub & Ethernet Device (Alternate ID) */
USB_DEVICE(0x0424, 0x9909),
.driver_info = (unsigned long) &smsc95xx_info,
},
{ }, /* END */ { }, /* END */
}; };
MODULE_DEVICE_TABLE(usb, products); MODULE_DEVICE_TABLE(usb, products);

View file

@ -1049,7 +1049,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
* NOTE: strictly conforming cdc-ether devices should expect * NOTE: strictly conforming cdc-ether devices should expect
* the ZLP here, but ignore the one-byte packet. * the ZLP here, but ignore the one-byte packet.
*/ */
if ((length % dev->maxpacket) == 0) { if (!(info->flags & FLAG_SEND_ZLP) && (length % dev->maxpacket) == 0) {
urb->transfer_buffer_length++; urb->transfer_buffer_length++;
if (skb_tailroom(skb)) { if (skb_tailroom(skb)) {
skb->data[skb->len] = 0; skb->data[skb->len] = 0;

View file

@ -64,6 +64,8 @@ static struct usb_device_id ar9170_usb_ids[] = {
{ USB_DEVICE(0x0cf3, 0x9170) }, { USB_DEVICE(0x0cf3, 0x9170) },
/* Atheros TG121N */ /* Atheros TG121N */
{ USB_DEVICE(0x0cf3, 0x1001) }, { USB_DEVICE(0x0cf3, 0x1001) },
/* TP-Link TL-WN821N v2 */
{ USB_DEVICE(0x0cf3, 0x1002) },
/* Cace Airpcap NX */ /* Cace Airpcap NX */
{ USB_DEVICE(0xcace, 0x0300) }, { USB_DEVICE(0xcace, 0x0300) },
/* D-Link DWA 160A */ /* D-Link DWA 160A */

View file

@ -609,14 +609,24 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
AR_PHY_CH1_EXT_CCA, AR_PHY_CH1_EXT_CCA,
AR_PHY_CH2_EXT_CCA AR_PHY_CH2_EXT_CCA
}; };
u8 chainmask; u8 chainmask, rx_chain_status;
rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK);
if (AR_SREV_9285(ah)) if (AR_SREV_9285(ah))
chainmask = 0x9; chainmask = 0x9;
else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) {
chainmask = 0x1B; if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4))
else chainmask = 0x1B;
chainmask = 0x3F; else
chainmask = 0x09;
} else {
if (rx_chain_status & 0x4)
chainmask = 0x3F;
else if (rx_chain_status & 0x2)
chainmask = 0x1B;
else
chainmask = 0x09;
}
h = ah->nfCalHist; h = ah->nfCalHist;
@ -697,6 +707,8 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah)
noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE; noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE;
else if (AR_SREV_9285(ah)) else if (AR_SREV_9285(ah))
noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE; noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE;
else if (AR_SREV_9287(ah))
noise_floor = AR_PHY_CCA_MAX_AR9287_GOOD_VALUE;
else else
noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE; noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE;
@ -924,6 +936,7 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah, bool is_reset)
regVal |= (1 << (19 + i)); regVal |= (1 << (19 + i));
REG_WRITE(ah, 0x7834, regVal); REG_WRITE(ah, 0x7834, regVal);
udelay(1); udelay(1);
regVal = REG_READ(ah, 0x7834);
regVal &= (~(0x1 << (19 + i))); regVal &= (~(0x1 << (19 + i)));
reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
regVal |= (reg_field << (19 + i)); regVal |= (reg_field << (19 + i));

View file

@ -28,6 +28,7 @@ extern const struct ath9k_percal_data adc_init_dc_cal;
#define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE -85 #define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE -85
#define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE -112 #define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE -112
#define AR_PHY_CCA_MAX_AR9285_GOOD_VALUE -118 #define AR_PHY_CCA_MAX_AR9285_GOOD_VALUE -118
#define AR_PHY_CCA_MAX_AR9287_GOOD_VALUE -118
#define AR_PHY_CCA_MAX_HIGH_VALUE -62 #define AR_PHY_CCA_MAX_HIGH_VALUE -62
#define AR_PHY_CCA_MIN_BAD_VALUE -140 #define AR_PHY_CCA_MIN_BAD_VALUE -140
#define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3 #define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3

View file

@ -509,6 +509,8 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
eep->baseEepHeader.dacLpMode); eep->baseEepHeader.dacLpMode);
udelay(100);
REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
pModal->miscBits >> 2); pModal->miscBits >> 2);
@ -902,7 +904,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
u16 powerLimit) u16 powerLimit)
{ {
#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */ #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;

View file

@ -842,7 +842,7 @@ static void ath9k_hw_init_mode_regs(struct ath_hw *ah)
static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
{ {
if (AR_SREV_9287_11(ah)) if (AR_SREV_9287_11_OR_LATER(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain, INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9287Modes_rx_gain_9287_1_1, ar9287Modes_rx_gain_9287_1_1,
ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6); ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6);
@ -853,7 +853,7 @@ static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
else if (AR_SREV_9280_20(ah)) else if (AR_SREV_9280_20(ah))
ath9k_hw_init_rxgain_ini(ah); ath9k_hw_init_rxgain_ini(ah);
if (AR_SREV_9287_11(ah)) { if (AR_SREV_9287_11_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9287Modes_tx_gain_9287_1_1, ar9287Modes_tx_gain_9287_1_1,
ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6); ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6);
@ -965,7 +965,7 @@ int ath9k_hw_init(struct ath_hw *ah)
ath9k_hw_init_mode_regs(ah); ath9k_hw_init_mode_regs(ah);
if (ah->is_pciexpress) if (ah->is_pciexpress)
ath9k_hw_configpcipowersave(ah, 0); ath9k_hw_configpcipowersave(ah, 0, 0);
else else
ath9k_hw_disablepcie(ah); ath9k_hw_disablepcie(ah);
@ -1273,6 +1273,15 @@ static void ath9k_hw_override_ini(struct ath_hw *ah,
*/ */
REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
if (AR_SREV_9280_10_OR_LATER(ah)) {
val = REG_READ(ah, AR_PCU_MISC_MODE2) &
(~AR_PCU_MISC_MODE2_HWWAR1);
if (AR_SREV_9287_10_OR_LATER(ah))
val = val & (~AR_PCU_MISC_MODE2_HWWAR2);
REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
}
if (!AR_SREV_5416_20_OR_LATER(ah) || if (!AR_SREV_5416_20_OR_LATER(ah) ||
AR_SREV_9280_10_OR_LATER(ah)) AR_SREV_9280_10_OR_LATER(ah))
@ -1784,7 +1793,7 @@ static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan,
static bool ath9k_hw_chip_reset(struct ath_hw *ah, static bool ath9k_hw_chip_reset(struct ath_hw *ah,
struct ath9k_channel *chan) struct ath9k_channel *chan)
{ {
if (OLC_FOR_AR9280_20_LATER) { if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) {
if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON))
return false; return false;
} else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) } else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
@ -2338,6 +2347,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
struct ath9k_channel *curchan = ah->curchan; struct ath9k_channel *curchan = ah->curchan;
u32 saveDefAntenna; u32 saveDefAntenna;
u32 macStaId1; u32 macStaId1;
u64 tsf = 0;
int i, rx_chainmask, r; int i, rx_chainmask, r;
ah->extprotspacing = sc->ht_extprotspacing; ah->extprotspacing = sc->ht_extprotspacing;
@ -2347,7 +2357,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
return -EIO; return -EIO;
if (curchan) if (curchan && !ah->chip_fullsleep)
ath9k_hw_getnf(ah, curchan); ath9k_hw_getnf(ah, curchan);
if (bChannelChange && if (bChannelChange &&
@ -2356,8 +2366,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
(chan->channel != ah->curchan->channel) && (chan->channel != ah->curchan->channel) &&
((chan->channelFlags & CHANNEL_ALL) == ((chan->channelFlags & CHANNEL_ALL) ==
(ah->curchan->channelFlags & CHANNEL_ALL)) && (ah->curchan->channelFlags & CHANNEL_ALL)) &&
(!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) && !(AR_SREV_9280(ah) || IS_CHAN_A_5MHZ_SPACED(chan) ||
!IS_CHAN_A_5MHZ_SPACED(ah->curchan)))) { IS_CHAN_A_5MHZ_SPACED(ah->curchan))) {
if (ath9k_hw_channel_change(ah, chan, sc->tx_chan_width)) { if (ath9k_hw_channel_change(ah, chan, sc->tx_chan_width)) {
ath9k_hw_loadnf(ah, ah->curchan); ath9k_hw_loadnf(ah, ah->curchan);
@ -2372,6 +2382,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
/* For chips on which RTC reset is done, save TSF before it gets cleared */
if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
tsf = ath9k_hw_gettsf64(ah);
saveLedState = REG_READ(ah, AR_CFG_LED) & saveLedState = REG_READ(ah, AR_CFG_LED) &
(AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW); AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW);
@ -2398,6 +2412,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
udelay(50); udelay(50);
} }
/* Restore TSF */
if (tsf && AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
ath9k_hw_settsf64(ah, tsf);
if (AR_SREV_9280_10_OR_LATER(ah)) if (AR_SREV_9280_10_OR_LATER(ah))
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
@ -3005,9 +3023,10 @@ void ath9k_ps_restore(struct ath_softc *sc)
* Programming the SerDes must go through the same 288 bit serial shift * Programming the SerDes must go through the same 288 bit serial shift
* register as the other analog registers. Hence the 9 writes. * register as the other analog registers. Hence the 9 writes.
*/ */
void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore) void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off)
{ {
u8 i; u8 i;
u32 val;
if (ah->is_pciexpress != true) if (ah->is_pciexpress != true)
return; return;
@ -3017,84 +3036,113 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore)
return; return;
/* Nothing to do on restore for 11N */ /* Nothing to do on restore for 11N */
if (restore) if (!restore) {
return; if (AR_SREV_9280_20_OR_LATER(ah)) {
/*
* AR9280 2.0 or later chips use SerDes values from the
* initvals.h initialized depending on chipset during
* ath9k_hw_init()
*/
for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
INI_RA(&ah->iniPcieSerdes, i, 1));
}
} else if (AR_SREV_9280(ah) &&
(ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) {
REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00);
REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
if (AR_SREV_9280_20_OR_LATER(ah)) { /* RX shut off when elecidle is asserted */
/* REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019);
* AR9280 2.0 or later chips use SerDes values from the REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820);
* initvals.h initialized depending on chipset during REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560);
* ath9k_hw_init()
*/ /* Shut off CLKREQ active in L1 */
for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) { if (ah->config.pcie_clock_req)
REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0), REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc);
INI_RA(&ah->iniPcieSerdes, i, 1)); else
REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd);
REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007);
/* Load the new settings */
REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
} else {
REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
/* RX shut off when elecidle is asserted */
REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
/*
* Ignore ah->ah_config.pcie_clock_req setting for
* pre-AR9280 11n
*/
REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
/* Load the new settings */
REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
} }
} else if (AR_SREV_9280(ah) &&
(ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) {
REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00);
REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
/* RX shut off when elecidle is asserted */ udelay(1000);
REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019);
REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820);
REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560);
/* Shut off CLKREQ active in L1 */ /* set bit 19 to allow forcing of pcie core into L1 state */
if (ah->config.pcie_clock_req) REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc);
else
REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd);
REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); /* Several PCIe massages to ensure proper behaviour */
REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); if (ah->config.pcie_waen) {
REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007); val = ah->config.pcie_waen;
if (!power_off)
val &= (~AR_WA_D3_L1_DISABLE);
} else {
if (AR_SREV_9285(ah) || AR_SREV_9271(ah) ||
AR_SREV_9287(ah)) {
val = AR9285_WA_DEFAULT;
if (!power_off)
val &= (~AR_WA_D3_L1_DISABLE);
} else if (AR_SREV_9280(ah)) {
/*
* On AR9280 chips bit 22 of 0x4004 needs to be
* set otherwise card may disappear.
*/
val = AR9280_WA_DEFAULT;
if (!power_off)
val &= (~AR_WA_D3_L1_DISABLE);
} else
val = AR_WA_DEFAULT;
}
/* Load the new settings */ REG_WRITE(ah, AR_WA, val);
REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
} else {
REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
/* RX shut off when elecidle is asserted */
REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
/*
* Ignore ah->ah_config.pcie_clock_req setting for
* pre-AR9280 11n
*/
REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
/* Load the new settings */
REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
} }
udelay(1000); if (power_off) {
/* set bit 19 to allow forcing of pcie core into L1 state */
REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
/* Several PCIe massages to ensure proper behaviour */
if (ah->config.pcie_waen) {
REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
} else {
if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah))
REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT);
/* /*
* On AR9280 chips bit 22 of 0x4004 needs to be set to * Set PCIe workaround bits
* otherwise card may disappear. * bit 14 in WA register (disable L1) should only
* be set when device enters D3 and be cleared
* when device comes back to D0.
*/ */
else if (AR_SREV_9280(ah)) if (ah->config.pcie_waen) {
REG_WRITE(ah, AR_WA, AR9280_WA_DEFAULT); if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
else REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE);
REG_WRITE(ah, AR_WA, AR_WA_DEFAULT); } else {
if (((AR_SREV_9285(ah) || AR_SREV_9271(ah) ||
AR_SREV_9287(ah)) &&
(AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) ||
(AR_SREV_9280(ah) &&
(AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) {
REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE);
}
}
} }
} }
@ -3652,15 +3700,7 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah)
} }
#endif #endif
if ((ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
(ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE) ||
(ah->hw_version.macVersion == AR_SREV_VERSION_9160) ||
(ah->hw_version.macVersion == AR_SREV_VERSION_9100) ||
(ah->hw_version.macVersion == AR_SREV_VERSION_9280) ||
(ah->hw_version.macVersion == AR_SREV_VERSION_9285))
pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
else
pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP;
if (AR_SREV_9280(ah) || AR_SREV_9285(ah)) if (AR_SREV_9280(ah) || AR_SREV_9285(ah))
pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS; pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS;

View file

@ -106,7 +106,7 @@
#define AH_TSF_WRITE_TIMEOUT 100 /* (us) */ #define AH_TSF_WRITE_TIMEOUT 100 /* (us) */
#define AH_TIME_QUANTUM 10 #define AH_TIME_QUANTUM 10
#define AR_KEYTABLE_SIZE 128 #define AR_KEYTABLE_SIZE 128
#define POWER_UP_TIME 200000 #define POWER_UP_TIME 10000
#define SPUR_RSSI_THRESH 40 #define SPUR_RSSI_THRESH 40
#define CAB_TIMEOUT_VAL 10 #define CAB_TIMEOUT_VAL 10
@ -650,7 +650,7 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
const struct ath9k_beacon_state *bs); const struct ath9k_beacon_state *bs);
bool ath9k_hw_setpower(struct ath_hw *ah, bool ath9k_hw_setpower(struct ath_hw *ah,
enum ath9k_power_mode mode); enum ath9k_power_mode mode);
void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore); void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off);
/* Interrupt Handling */ /* Interrupt Handling */
bool ath9k_hw_intrpend(struct ath_hw *ah); bool ath9k_hw_intrpend(struct ath_hw *ah);

View file

@ -1131,7 +1131,7 @@ void ath_radio_enable(struct ath_softc *sc)
int r; int r;
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
ath9k_hw_configpcipowersave(ah, 0); ath9k_hw_configpcipowersave(ah, 0, 0);
if (!ah->curchan) if (!ah->curchan)
ah->curchan = ath_get_curchannel(sc, sc->hw); ah->curchan = ath_get_curchannel(sc, sc->hw);
@ -1202,7 +1202,7 @@ void ath_radio_disable(struct ath_softc *sc)
spin_unlock_bh(&sc->sc_resetlock); spin_unlock_bh(&sc->sc_resetlock);
ath9k_hw_phy_disable(ah); ath9k_hw_phy_disable(ah);
ath9k_hw_configpcipowersave(ah, 1); ath9k_hw_configpcipowersave(ah, 1, 1);
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
} }
@ -1226,11 +1226,6 @@ static void ath9k_rfkill_poll_state(struct ieee80211_hw *hw)
bool blocked = !!ath_is_rfkill_set(sc); bool blocked = !!ath_is_rfkill_set(sc);
wiphy_rfkill_set_hw_state(hw->wiphy, blocked); wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
if (blocked)
ath_radio_disable(sc);
else
ath_radio_enable(sc);
} }
static void ath_start_rfkill_poll(struct ath_softc *sc) static void ath_start_rfkill_poll(struct ath_softc *sc)
@ -1260,6 +1255,7 @@ void ath_detach(struct ath_softc *sc)
DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n"); DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n");
ath_deinit_leds(sc); ath_deinit_leds(sc);
wiphy_rfkill_stop_polling(sc->hw->wiphy);
for (i = 0; i < sc->num_sec_wiphy; i++) { for (i = 0; i < sc->num_sec_wiphy; i++) {
struct ath_wiphy *aphy = sc->sec_wiphy[i]; struct ath_wiphy *aphy = sc->sec_wiphy[i];
@ -1942,7 +1938,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
init_channel = ath_get_curchannel(sc, hw); init_channel = ath_get_curchannel(sc, hw);
/* Reset SERDES registers */ /* Reset SERDES registers */
ath9k_hw_configpcipowersave(sc->sc_ah, 0); ath9k_hw_configpcipowersave(sc->sc_ah, 0, 0);
/* /*
* The basic interface to setting the hardware in a good * The basic interface to setting the hardware in a good
@ -2166,11 +2162,9 @@ static void ath9k_stop(struct ieee80211_hw *hw)
} else } else
sc->rx.rxlink = NULL; sc->rx.rxlink = NULL;
wiphy_rfkill_stop_polling(sc->hw->wiphy);
/* disable HAL and put h/w to sleep */ /* disable HAL and put h/w to sleep */
ath9k_hw_disable(sc->sc_ah); ath9k_hw_disable(sc->sc_ah);
ath9k_hw_configpcipowersave(sc->sc_ah, 1); ath9k_hw_configpcipowersave(sc->sc_ah, 1, 1);
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
sc->sc_flags |= SC_OP_INVALID; sc->sc_flags |= SC_OP_INVALID;

View file

@ -676,8 +676,9 @@
#define AR_RC_HOSTIF 0x00000100 #define AR_RC_HOSTIF 0x00000100
#define AR_WA 0x4004 #define AR_WA 0x4004
#define AR_WA_D3_L1_DISABLE (1 << 14)
#define AR9285_WA_DEFAULT 0x004a05cb #define AR9285_WA_DEFAULT 0x004a05cb
#define AR9280_WA_DEFAULT 0x0040073f #define AR9280_WA_DEFAULT 0x0040073b
#define AR_WA_DEFAULT 0x0000073f #define AR_WA_DEFAULT 0x0000073f

View file

@ -61,11 +61,28 @@ config B43_PCMCIA
If unsure, say N. If unsure, say N.
config B43_SDIO
bool "Broadcom 43xx SDIO device support (EXPERIMENTAL)"
depends on B43 && SSB_SDIOHOST_POSSIBLE && EXPERIMENTAL
select SSB_SDIOHOST
---help---
Broadcom 43xx device support for Soft-MAC SDIO devices.
With this config option you can drive Soft-MAC b43 cards with a
Secure Digital I/O interface.
This includes the WLAN daughter card found on the Nintendo Wii
video game console.
Note that this does not support Broadcom 43xx Full-MAC devices.
It's safe to select Y here, even if you don't have a B43 SDIO device.
If unsure, say N.
# Data transfers to the device via PIO # Data transfers to the device via PIO
# This is only needed on PCMCIA devices. All others can do DMA properly. # This is only needed on PCMCIA and SDIO devices. All others can do DMA properly.
config B43_PIO config B43_PIO
bool bool
depends on B43 && (B43_PCMCIA || B43_FORCE_PIO) depends on B43 && (B43_SDIO || B43_PCMCIA || B43_FORCE_PIO)
select SSB_BLOCKIO select SSB_BLOCKIO
default y default y

View file

@ -16,6 +16,7 @@ b43-$(CONFIG_B43_PIO) += pio.o
b43-y += rfkill.o b43-y += rfkill.o
b43-$(CONFIG_B43_LEDS) += leds.o b43-$(CONFIG_B43_LEDS) += leds.o
b43-$(CONFIG_B43_PCMCIA) += pcmcia.o b43-$(CONFIG_B43_PCMCIA) += pcmcia.o
b43-$(CONFIG_B43_SDIO) += sdio.o
b43-$(CONFIG_B43_DEBUG) += debugfs.o b43-$(CONFIG_B43_DEBUG) += debugfs.o
obj-$(CONFIG_B43) += b43.o obj-$(CONFIG_B43) += b43.o

View file

@ -629,13 +629,6 @@ struct b43_wl {
* from the mac80211 subsystem. */ * from the mac80211 subsystem. */
u16 mac80211_initially_registered_queues; u16 mac80211_initially_registered_queues;
/* R/W lock for data transmission.
* Transmissions on 2+ queues can run concurrently, but somebody else
* might sync with TX by write_lock_irqsave()'ing. */
rwlock_t tx_lock;
/* Lock for LEDs access. */
spinlock_t leds_lock;
/* We can only have one operating interface (802.11 core) /* We can only have one operating interface (802.11 core)
* at a time. General information about this interface follows. * at a time. General information about this interface follows.
*/ */
@ -686,6 +679,9 @@ struct b43_wl {
struct work_struct tx_work; struct work_struct tx_work;
/* Queue of packets to be transmitted. */ /* Queue of packets to be transmitted. */
struct sk_buff_head tx_queue; struct sk_buff_head tx_queue;
/* The device LEDs. */
struct b43_leds leds;
}; };
/* The type of the firmware file. */ /* The type of the firmware file. */
@ -768,13 +764,10 @@ struct b43_wldev {
/* The device initialization status. /* The device initialization status.
* Use b43_status() to query. */ * Use b43_status() to query. */
atomic_t __init_status; atomic_t __init_status;
/* Saved init status for handling suspend. */
int suspend_init_status;
bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */ bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */
bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */ bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */
bool radio_hw_enable; /* saved state of radio hardware enabled state */ bool radio_hw_enable; /* saved state of radio hardware enabled state */
bool suspend_in_progress; /* TRUE, if we are in a suspend/resume cycle */
bool qos_enabled; /* TRUE, if QoS is used. */ bool qos_enabled; /* TRUE, if QoS is used. */
bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */ bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */
@ -794,12 +787,6 @@ struct b43_wldev {
/* Various statistics about the physical device. */ /* Various statistics about the physical device. */
struct b43_stats stats; struct b43_stats stats;
/* The device LEDs. */
struct b43_led led_tx;
struct b43_led led_rx;
struct b43_led led_assoc;
struct b43_led led_radio;
/* Reason code of the last interrupt. */ /* Reason code of the last interrupt. */
u32 irq_reason; u32 irq_reason;
u32 dma_reason[6]; u32 dma_reason[6];
@ -830,6 +817,10 @@ struct b43_wldev {
/* Debugging stuff follows. */ /* Debugging stuff follows. */
#ifdef CONFIG_B43_DEBUG #ifdef CONFIG_B43_DEBUG
struct b43_dfsentry *dfsentry; struct b43_dfsentry *dfsentry;
unsigned int irq_count;
unsigned int irq_bit_count[32];
unsigned int tx_count;
unsigned int rx_count;
#endif #endif
}; };

View file

@ -689,6 +689,7 @@ static void b43_add_dynamic_debug(struct b43_wldev *dev)
add_dyn_dbg("debug_lo", B43_DBG_LO, 0); add_dyn_dbg("debug_lo", B43_DBG_LO, 0);
add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0); add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0);
add_dyn_dbg("debug_keys", B43_DBG_KEYS, 0); add_dyn_dbg("debug_keys", B43_DBG_KEYS, 0);
add_dyn_dbg("debug_verbose_stats", B43_DBG_VERBOSESTATS, 0);
#undef add_dyn_dbg #undef add_dyn_dbg
} }

View file

@ -13,6 +13,7 @@ enum b43_dyndbg { /* Dynamic debugging features */
B43_DBG_LO, B43_DBG_LO,
B43_DBG_FIRMWARE, B43_DBG_FIRMWARE,
B43_DBG_KEYS, B43_DBG_KEYS,
B43_DBG_VERBOSESTATS,
__B43_NR_DYNDBG, __B43_NR_DYNDBG,
}; };

View file

@ -1428,9 +1428,9 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
ring->nr_failed_tx_packets++; ring->nr_failed_tx_packets++;
ring->nr_total_packet_tries += status->frame_count; ring->nr_total_packet_tries += status->frame_count;
#endif /* DEBUG */ #endif /* DEBUG */
ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb); ieee80211_tx_status(dev->wl->hw, meta->skb);
/* skb is freed by ieee80211_tx_status_irqsafe() */ /* skb is freed by ieee80211_tx_status() */
meta->skb = NULL; meta->skb = NULL;
} else { } else {
/* No need to call free_descriptor_buffer here, as /* No need to call free_descriptor_buffer here, as

View file

@ -34,35 +34,75 @@
static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index, static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index,
bool activelow) bool activelow)
{ {
struct b43_wl *wl = dev->wl;
unsigned long flags;
u16 ctl; u16 ctl;
spin_lock_irqsave(&wl->leds_lock, flags);
ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL); ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL);
if (activelow) if (activelow)
ctl &= ~(1 << led_index); ctl &= ~(1 << led_index);
else else
ctl |= (1 << led_index); ctl |= (1 << led_index);
b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl); b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl);
spin_unlock_irqrestore(&wl->leds_lock, flags);
} }
static void b43_led_turn_off(struct b43_wldev *dev, u8 led_index, static void b43_led_turn_off(struct b43_wldev *dev, u8 led_index,
bool activelow) bool activelow)
{ {
struct b43_wl *wl = dev->wl;
unsigned long flags;
u16 ctl; u16 ctl;
spin_lock_irqsave(&wl->leds_lock, flags);
ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL); ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL);
if (activelow) if (activelow)
ctl |= (1 << led_index); ctl |= (1 << led_index);
else else
ctl &= ~(1 << led_index); ctl &= ~(1 << led_index);
b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl); b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl);
spin_unlock_irqrestore(&wl->leds_lock, flags); }
static void b43_led_update(struct b43_wldev *dev,
struct b43_led *led)
{
bool radio_enabled;
bool turn_on;
if (!led->wl)
return;
radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable);
/* The led->state read is racy, but we don't care. In case we raced
* with the brightness_set handler, we will be called again soon
* to fixup our state. */
if (radio_enabled)
turn_on = atomic_read(&led->state) != LED_OFF;
else
turn_on = 0;
if (turn_on == led->hw_state)
return;
led->hw_state = turn_on;
if (turn_on)
b43_led_turn_on(dev, led->index, led->activelow);
else
b43_led_turn_off(dev, led->index, led->activelow);
}
static void b43_leds_work(struct work_struct *work)
{
struct b43_leds *leds = container_of(work, struct b43_leds, work);
struct b43_wl *wl = container_of(leds, struct b43_wl, leds);
struct b43_wldev *dev;
mutex_lock(&wl->mutex);
dev = wl->current_dev;
if (unlikely(!dev || b43_status(dev) < B43_STAT_STARTED))
goto out_unlock;
b43_led_update(dev, &wl->leds.led_tx);
b43_led_update(dev, &wl->leds.led_rx);
b43_led_update(dev, &wl->leds.led_radio);
b43_led_update(dev, &wl->leds.led_assoc);
out_unlock:
mutex_unlock(&wl->mutex);
} }
/* Callback from the LED subsystem. */ /* Callback from the LED subsystem. */
@ -70,21 +110,12 @@ static void b43_led_brightness_set(struct led_classdev *led_dev,
enum led_brightness brightness) enum led_brightness brightness)
{ {
struct b43_led *led = container_of(led_dev, struct b43_led, led_dev); struct b43_led *led = container_of(led_dev, struct b43_led, led_dev);
struct b43_wldev *dev = led->dev; struct b43_wl *wl = led->wl;
bool radio_enabled;
if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) if (likely(!wl->leds.stop)) {
return; atomic_set(&led->state, brightness);
ieee80211_queue_work(wl->hw, &wl->leds.work);
/* Checking the radio-enabled status here is slightly racy, }
* but we want to avoid the locking overhead and we don't care
* whether the LED has the wrong state for a second. */
radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable);
if (brightness == LED_OFF || !radio_enabled)
b43_led_turn_off(dev, led->index, led->activelow);
else
b43_led_turn_on(dev, led->index, led->activelow);
} }
static int b43_register_led(struct b43_wldev *dev, struct b43_led *led, static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
@ -93,15 +124,15 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
{ {
int err; int err;
b43_led_turn_off(dev, led_index, activelow); if (led->wl)
if (led->dev)
return -EEXIST; return -EEXIST;
if (!default_trigger) if (!default_trigger)
return -EINVAL; return -EINVAL;
led->dev = dev; led->wl = dev->wl;
led->index = led_index; led->index = led_index;
led->activelow = activelow; led->activelow = activelow;
strncpy(led->name, name, sizeof(led->name)); strncpy(led->name, name, sizeof(led->name));
atomic_set(&led->state, 0);
led->led_dev.name = led->name; led->led_dev.name = led->name;
led->led_dev.default_trigger = default_trigger; led->led_dev.default_trigger = default_trigger;
@ -110,19 +141,19 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
err = led_classdev_register(dev->dev->dev, &led->led_dev); err = led_classdev_register(dev->dev->dev, &led->led_dev);
if (err) { if (err) {
b43warn(dev->wl, "LEDs: Failed to register %s\n", name); b43warn(dev->wl, "LEDs: Failed to register %s\n", name);
led->dev = NULL; led->wl = NULL;
return err; return err;
} }
return 0; return 0;
} }
static void b43_unregister_led(struct b43_led *led) static void b43_unregister_led(struct b43_led *led)
{ {
if (!led->dev) if (!led->wl)
return; return;
led_classdev_unregister(&led->led_dev); led_classdev_unregister(&led->led_dev);
b43_led_turn_off(led->dev, led->index, led->activelow); led->wl = NULL;
led->dev = NULL;
} }
static void b43_map_led(struct b43_wldev *dev, static void b43_map_led(struct b43_wldev *dev,
@ -137,24 +168,20 @@ static void b43_map_led(struct b43_wldev *dev,
* generic LED triggers. */ * generic LED triggers. */
switch (behaviour) { switch (behaviour) {
case B43_LED_INACTIVE: case B43_LED_INACTIVE:
break;
case B43_LED_OFF: case B43_LED_OFF:
b43_led_turn_off(dev, led_index, activelow);
break;
case B43_LED_ON: case B43_LED_ON:
b43_led_turn_on(dev, led_index, activelow);
break; break;
case B43_LED_ACTIVITY: case B43_LED_ACTIVITY:
case B43_LED_TRANSFER: case B43_LED_TRANSFER:
case B43_LED_APTRANSFER: case B43_LED_APTRANSFER:
snprintf(name, sizeof(name), snprintf(name, sizeof(name),
"b43-%s::tx", wiphy_name(hw->wiphy)); "b43-%s::tx", wiphy_name(hw->wiphy));
b43_register_led(dev, &dev->led_tx, name, b43_register_led(dev, &dev->wl->leds.led_tx, name,
ieee80211_get_tx_led_name(hw), ieee80211_get_tx_led_name(hw),
led_index, activelow); led_index, activelow);
snprintf(name, sizeof(name), snprintf(name, sizeof(name),
"b43-%s::rx", wiphy_name(hw->wiphy)); "b43-%s::rx", wiphy_name(hw->wiphy));
b43_register_led(dev, &dev->led_rx, name, b43_register_led(dev, &dev->wl->leds.led_rx, name,
ieee80211_get_rx_led_name(hw), ieee80211_get_rx_led_name(hw),
led_index, activelow); led_index, activelow);
break; break;
@ -164,18 +191,15 @@ static void b43_map_led(struct b43_wldev *dev,
case B43_LED_MODE_BG: case B43_LED_MODE_BG:
snprintf(name, sizeof(name), snprintf(name, sizeof(name),
"b43-%s::radio", wiphy_name(hw->wiphy)); "b43-%s::radio", wiphy_name(hw->wiphy));
b43_register_led(dev, &dev->led_radio, name, b43_register_led(dev, &dev->wl->leds.led_radio, name,
ieee80211_get_radio_led_name(hw), ieee80211_get_radio_led_name(hw),
led_index, activelow); led_index, activelow);
/* Sync the RF-kill LED state with radio and switch states. */
if (dev->phy.radio_on && b43_is_hw_radio_enabled(dev))
b43_led_turn_on(dev, led_index, activelow);
break; break;
case B43_LED_WEIRD: case B43_LED_WEIRD:
case B43_LED_ASSOC: case B43_LED_ASSOC:
snprintf(name, sizeof(name), snprintf(name, sizeof(name),
"b43-%s::assoc", wiphy_name(hw->wiphy)); "b43-%s::assoc", wiphy_name(hw->wiphy));
b43_register_led(dev, &dev->led_assoc, name, b43_register_led(dev, &dev->wl->leds.led_assoc, name,
ieee80211_get_assoc_led_name(hw), ieee80211_get_assoc_led_name(hw),
led_index, activelow); led_index, activelow);
break; break;
@ -186,58 +210,150 @@ static void b43_map_led(struct b43_wldev *dev,
} }
} }
void b43_leds_init(struct b43_wldev *dev) static void b43_led_get_sprominfo(struct b43_wldev *dev,
unsigned int led_index,
enum b43_led_behaviour *behaviour,
bool *activelow)
{ {
struct ssb_bus *bus = dev->dev->bus; struct ssb_bus *bus = dev->dev->bus;
u8 sprom[4]; u8 sprom[4];
int i;
enum b43_led_behaviour behaviour;
bool activelow;
sprom[0] = bus->sprom.gpio0; sprom[0] = bus->sprom.gpio0;
sprom[1] = bus->sprom.gpio1; sprom[1] = bus->sprom.gpio1;
sprom[2] = bus->sprom.gpio2; sprom[2] = bus->sprom.gpio2;
sprom[3] = bus->sprom.gpio3; sprom[3] = bus->sprom.gpio3;
for (i = 0; i < 4; i++) { if (sprom[led_index] == 0xFF) {
if (sprom[i] == 0xFF) { /* There is no LED information in the SPROM
/* There is no LED information in the SPROM * for this LED. Hardcode it here. */
* for this LED. Hardcode it here. */ *activelow = 0;
activelow = 0; switch (led_index) {
switch (i) { case 0:
case 0: *behaviour = B43_LED_ACTIVITY;
behaviour = B43_LED_ACTIVITY; *activelow = 1;
activelow = 1; if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ) *behaviour = B43_LED_RADIO_ALL;
behaviour = B43_LED_RADIO_ALL; break;
break; case 1:
case 1: *behaviour = B43_LED_RADIO_B;
behaviour = B43_LED_RADIO_B; if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK) *behaviour = B43_LED_ASSOC;
behaviour = B43_LED_ASSOC; break;
break; case 2:
case 2: *behaviour = B43_LED_RADIO_A;
behaviour = B43_LED_RADIO_A; break;
break; case 3:
case 3: *behaviour = B43_LED_OFF;
behaviour = B43_LED_OFF; break;
break; default:
default: B43_WARN_ON(1);
B43_WARN_ON(1); return;
return;
}
} else {
behaviour = sprom[i] & B43_LED_BEHAVIOUR;
activelow = !!(sprom[i] & B43_LED_ACTIVELOW);
} }
b43_map_led(dev, i, behaviour, activelow); } else {
*behaviour = sprom[led_index] & B43_LED_BEHAVIOUR;
*activelow = !!(sprom[led_index] & B43_LED_ACTIVELOW);
} }
} }
void b43_leds_init(struct b43_wldev *dev)
{
struct b43_led *led;
unsigned int i;
enum b43_led_behaviour behaviour;
bool activelow;
/* Sync the RF-kill LED state (if we have one) with radio and switch states. */
led = &dev->wl->leds.led_radio;
if (led->wl) {
if (dev->phy.radio_on && b43_is_hw_radio_enabled(dev)) {
b43_led_turn_on(dev, led->index, led->activelow);
led->hw_state = 1;
atomic_set(&led->state, 1);
} else {
b43_led_turn_off(dev, led->index, led->activelow);
led->hw_state = 0;
atomic_set(&led->state, 0);
}
}
/* Initialize TX/RX/ASSOC leds */
led = &dev->wl->leds.led_tx;
if (led->wl) {
b43_led_turn_off(dev, led->index, led->activelow);
led->hw_state = 0;
atomic_set(&led->state, 0);
}
led = &dev->wl->leds.led_rx;
if (led->wl) {
b43_led_turn_off(dev, led->index, led->activelow);
led->hw_state = 0;
atomic_set(&led->state, 0);
}
led = &dev->wl->leds.led_assoc;
if (led->wl) {
b43_led_turn_off(dev, led->index, led->activelow);
led->hw_state = 0;
atomic_set(&led->state, 0);
}
/* Initialize other LED states. */
for (i = 0; i < B43_MAX_NR_LEDS; i++) {
b43_led_get_sprominfo(dev, i, &behaviour, &activelow);
switch (behaviour) {
case B43_LED_OFF:
b43_led_turn_off(dev, i, activelow);
break;
case B43_LED_ON:
b43_led_turn_on(dev, i, activelow);
break;
default:
/* Leave others as-is. */
break;
}
}
dev->wl->leds.stop = 0;
}
void b43_leds_exit(struct b43_wldev *dev) void b43_leds_exit(struct b43_wldev *dev)
{ {
b43_unregister_led(&dev->led_tx); struct b43_leds *leds = &dev->wl->leds;
b43_unregister_led(&dev->led_rx);
b43_unregister_led(&dev->led_assoc); b43_led_turn_off(dev, leds->led_tx.index, leds->led_tx.activelow);
b43_unregister_led(&dev->led_radio); b43_led_turn_off(dev, leds->led_rx.index, leds->led_rx.activelow);
b43_led_turn_off(dev, leds->led_assoc.index, leds->led_assoc.activelow);
b43_led_turn_off(dev, leds->led_radio.index, leds->led_radio.activelow);
}
void b43_leds_stop(struct b43_wldev *dev)
{
struct b43_leds *leds = &dev->wl->leds;
leds->stop = 1;
cancel_work_sync(&leds->work);
}
void b43_leds_register(struct b43_wldev *dev)
{
unsigned int i;
enum b43_led_behaviour behaviour;
bool activelow;
INIT_WORK(&dev->wl->leds.work, b43_leds_work);
/* Register the LEDs to the LED subsystem. */
for (i = 0; i < B43_MAX_NR_LEDS; i++) {
b43_led_get_sprominfo(dev, i, &behaviour, &activelow);
b43_map_led(dev, i, behaviour, activelow);
}
}
void b43_leds_unregister(struct b43_wldev *dev)
{
struct b43_leds *leds = &dev->wl->leds;
b43_unregister_led(&leds->led_tx);
b43_unregister_led(&leds->led_rx);
b43_unregister_led(&leds->led_assoc);
b43_unregister_led(&leds->led_radio);
} }

View file

@ -7,12 +7,13 @@ struct b43_wldev;
#include <linux/types.h> #include <linux/types.h>
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/workqueue.h>
#define B43_LED_MAX_NAME_LEN 31 #define B43_LED_MAX_NAME_LEN 31
struct b43_led { struct b43_led {
struct b43_wldev *dev; struct b43_wl *wl;
/* The LED class device */ /* The LED class device */
struct led_classdev led_dev; struct led_classdev led_dev;
/* The index number of the LED. */ /* The index number of the LED. */
@ -22,8 +23,24 @@ struct b43_led {
bool activelow; bool activelow;
/* The unique name string for this LED device. */ /* The unique name string for this LED device. */
char name[B43_LED_MAX_NAME_LEN + 1]; char name[B43_LED_MAX_NAME_LEN + 1];
/* The current status of the LED. This is updated locklessly. */
atomic_t state;
/* The active state in hardware. */
bool hw_state;
}; };
struct b43_leds {
struct b43_led led_tx;
struct b43_led led_rx;
struct b43_led led_radio;
struct b43_led led_assoc;
bool stop;
struct work_struct work;
};
#define B43_MAX_NR_LEDS 4
#define B43_LED_BEHAVIOUR 0x7F #define B43_LED_BEHAVIOUR 0x7F
#define B43_LED_ACTIVELOW 0x80 #define B43_LED_ACTIVELOW 0x80
/* LED behaviour values */ /* LED behaviour values */
@ -42,23 +59,35 @@ enum b43_led_behaviour {
B43_LED_INACTIVE, B43_LED_INACTIVE,
}; };
void b43_leds_register(struct b43_wldev *dev);
void b43_leds_unregister(struct b43_wldev *dev);
void b43_leds_init(struct b43_wldev *dev); void b43_leds_init(struct b43_wldev *dev);
void b43_leds_exit(struct b43_wldev *dev); void b43_leds_exit(struct b43_wldev *dev);
void b43_leds_stop(struct b43_wldev *dev);
#else /* CONFIG_B43_LEDS */ #else /* CONFIG_B43_LEDS */
/* LED support disabled */ /* LED support disabled */
struct b43_led { struct b43_leds {
/* empty */ /* empty */
}; };
static inline void b43_leds_register(struct b43_wldev *dev)
{
}
static inline void b43_leds_unregister(struct b43_wldev *dev)
{
}
static inline void b43_leds_init(struct b43_wldev *dev) static inline void b43_leds_init(struct b43_wldev *dev)
{ {
} }
static inline void b43_leds_exit(struct b43_wldev *dev) static inline void b43_leds_exit(struct b43_wldev *dev)
{ {
} }
static inline void b43_leds_stop(struct b43_wldev *dev)
{
}
#endif /* CONFIG_B43_LEDS */ #endif /* CONFIG_B43_LEDS */
#endif /* B43_LEDS_H_ */ #endif /* B43_LEDS_H_ */

View file

@ -8,6 +8,9 @@
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org> Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch> Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
SDIO support
Copyright (c) 2009 Albert Herranz <albert_herranz@yahoo.es>
Some parts of the code in this file are derived from the ipw2200 Some parts of the code in this file are derived from the ipw2200
driver Copyright(c) 2003 - 2004 Intel Corporation. driver Copyright(c) 2003 - 2004 Intel Corporation.
@ -53,6 +56,8 @@
#include "xmit.h" #include "xmit.h"
#include "lo.h" #include "lo.h"
#include "pcmcia.h" #include "pcmcia.h"
#include "sdio.h"
#include <linux/mmc/sdio_func.h>
MODULE_DESCRIPTION("Broadcom B43 wireless driver"); MODULE_DESCRIPTION("Broadcom B43 wireless driver");
MODULE_AUTHOR("Martin Langer"); MODULE_AUTHOR("Martin Langer");
@ -1587,7 +1592,7 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
dev = wl->current_dev; dev = wl->current_dev;
if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) { if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
if (0 /*FIXME dev->dev->bus->bustype == SSB_BUSTYPE_SDIO*/) { if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
/* wl->mutex is enough. */ /* wl->mutex is enough. */
b43_do_beacon_update_trigger_work(dev); b43_do_beacon_update_trigger_work(dev);
mmiowb(); mmiowb();
@ -1825,6 +1830,16 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev)
/* Re-enable interrupts on the device by restoring the current interrupt mask. */ /* Re-enable interrupts on the device by restoring the current interrupt mask. */
b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask); b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
#if B43_DEBUG
if (b43_debug(dev, B43_DBG_VERBOSESTATS)) {
dev->irq_count++;
for (i = 0; i < ARRAY_SIZE(dev->irq_bit_count); i++) {
if (reason & (1 << i))
dev->irq_bit_count[i]++;
}
}
#endif
} }
/* Interrupt thread handler. Handles device interrupts in thread context. */ /* Interrupt thread handler. Handles device interrupts in thread context. */
@ -1905,6 +1920,21 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
return ret; return ret;
} }
/* SDIO interrupt handler. This runs in process context. */
static void b43_sdio_interrupt_handler(struct b43_wldev *dev)
{
struct b43_wl *wl = dev->wl;
irqreturn_t ret;
mutex_lock(&wl->mutex);
ret = b43_do_interrupt(dev);
if (ret == IRQ_WAKE_THREAD)
b43_do_interrupt_thread(dev);
mutex_unlock(&wl->mutex);
}
void b43_do_release_fw(struct b43_firmware_file *fw) void b43_do_release_fw(struct b43_firmware_file *fw)
{ {
release_firmware(fw->data); release_firmware(fw->data);
@ -2645,6 +2675,20 @@ static void b43_adjust_opmode(struct b43_wldev *dev)
cfp_pretbtt = 50; cfp_pretbtt = 50;
} }
b43_write16(dev, 0x612, cfp_pretbtt); b43_write16(dev, 0x612, cfp_pretbtt);
/* FIXME: We don't currently implement the PMQ mechanism,
* so always disable it. If we want to implement PMQ,
* we need to enable it here (clear DISCPMQ) in AP mode.
*/
if (0 /* ctl & B43_MACCTL_AP */) {
b43_write32(dev, B43_MMIO_MACCTL,
b43_read32(dev, B43_MMIO_MACCTL)
& ~B43_MACCTL_DISCPMQ);
} else {
b43_write32(dev, B43_MMIO_MACCTL,
b43_read32(dev, B43_MMIO_MACCTL)
| B43_MACCTL_DISCPMQ);
}
} }
static void b43_rate_memory_write(struct b43_wldev *dev, u16 rate, int is_ofdm) static void b43_rate_memory_write(struct b43_wldev *dev, u16 rate, int is_ofdm)
@ -2873,6 +2917,27 @@ static void b43_periodic_every15sec(struct b43_wldev *dev)
atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
wmb(); wmb();
#if B43_DEBUG
if (b43_debug(dev, B43_DBG_VERBOSESTATS)) {
unsigned int i;
b43dbg(dev->wl, "Stats: %7u IRQs/sec, %7u TX/sec, %7u RX/sec\n",
dev->irq_count / 15,
dev->tx_count / 15,
dev->rx_count / 15);
dev->irq_count = 0;
dev->tx_count = 0;
dev->rx_count = 0;
for (i = 0; i < ARRAY_SIZE(dev->irq_bit_count); i++) {
if (dev->irq_bit_count[i]) {
b43dbg(dev->wl, "Stats: %7u IRQ-%02u/sec (0x%08X)\n",
dev->irq_bit_count[i] / 15, i, (1 << i));
dev->irq_bit_count[i] = 0;
}
}
}
#endif
} }
static void do_periodic_work(struct b43_wldev *dev) static void do_periodic_work(struct b43_wldev *dev)
@ -3002,14 +3067,18 @@ static void b43_security_init(struct b43_wldev *dev)
static int b43_rng_read(struct hwrng *rng, u32 *data) static int b43_rng_read(struct hwrng *rng, u32 *data)
{ {
struct b43_wl *wl = (struct b43_wl *)rng->priv; struct b43_wl *wl = (struct b43_wl *)rng->priv;
struct b43_wldev *dev;
int count = -ENODEV;
/* FIXME: We need to take wl->mutex here to make sure the device mutex_lock(&wl->mutex);
* is not going away from under our ass. However it could deadlock dev = wl->current_dev;
* with hwrng internal locking. */ if (likely(dev && b43_status(dev) >= B43_STAT_INITIALIZED)) {
*data = b43_read16(dev, B43_MMIO_RNG);
count = sizeof(u16);
}
mutex_unlock(&wl->mutex);
*data = b43_read16(wl->current_dev, B43_MMIO_RNG); return count;
return (sizeof(u16));
} }
#endif /* CONFIG_B43_HWRNG */ #endif /* CONFIG_B43_HWRNG */
@ -3068,6 +3137,9 @@ static void b43_tx_work(struct work_struct *work)
dev_kfree_skb(skb); /* Drop it */ dev_kfree_skb(skb); /* Drop it */
} }
#if B43_DEBUG
dev->tx_count++;
#endif
mutex_unlock(&wl->mutex); mutex_unlock(&wl->mutex);
} }
@ -3820,7 +3892,7 @@ redo:
/* Disable interrupts on the device. */ /* Disable interrupts on the device. */
b43_set_status(dev, B43_STAT_INITIALIZED); b43_set_status(dev, B43_STAT_INITIALIZED);
if (0 /*FIXME dev->dev->bus->bustype == SSB_BUSTYPE_SDIO*/) { if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
/* wl->mutex is locked. That is enough. */ /* wl->mutex is locked. That is enough. */
b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0); b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */ b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */
@ -3830,10 +3902,15 @@ redo:
b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */ b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */
spin_unlock_irq(&wl->hardirq_lock); spin_unlock_irq(&wl->hardirq_lock);
} }
/* Synchronize the interrupt handlers. Unlock to avoid deadlocks. */ /* Synchronize and free the interrupt handlers. Unlock to avoid deadlocks. */
orig_dev = dev; orig_dev = dev;
mutex_unlock(&wl->mutex); mutex_unlock(&wl->mutex);
synchronize_irq(dev->dev->irq); if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
b43_sdio_free_irq(dev);
} else {
synchronize_irq(dev->dev->irq);
free_irq(dev->dev->irq, dev);
}
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
dev = wl->current_dev; dev = wl->current_dev;
if (!dev) if (!dev)
@ -3850,7 +3927,7 @@ redo:
dev_kfree_skb(skb_dequeue(&wl->tx_queue)); dev_kfree_skb(skb_dequeue(&wl->tx_queue));
b43_mac_suspend(dev); b43_mac_suspend(dev);
free_irq(dev->dev->irq, dev); b43_leds_exit(dev);
b43dbg(wl, "Wireless interface stopped\n"); b43dbg(wl, "Wireless interface stopped\n");
return dev; return dev;
@ -3864,12 +3941,20 @@ static int b43_wireless_core_start(struct b43_wldev *dev)
B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED); B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED);
drain_txstatus_queue(dev); drain_txstatus_queue(dev);
err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler, if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
b43_interrupt_thread_handler, err = b43_sdio_request_irq(dev, b43_sdio_interrupt_handler);
IRQF_SHARED, KBUILD_MODNAME, dev); if (err) {
if (err) { b43err(dev->wl, "Cannot request SDIO IRQ\n");
b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq); goto out;
goto out; }
} else {
err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler,
b43_interrupt_thread_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (err) {
b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq);
goto out;
}
} }
/* We are ready to run. */ /* We are ready to run. */
@ -3882,8 +3967,10 @@ static int b43_wireless_core_start(struct b43_wldev *dev)
/* Start maintainance work */ /* Start maintainance work */
b43_periodic_tasks_setup(dev); b43_periodic_tasks_setup(dev);
b43_leds_init(dev);
b43dbg(dev->wl, "Wireless interface started\n"); b43dbg(dev->wl, "Wireless interface started\n");
out: out:
return err; return err;
} }
@ -4160,10 +4247,6 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
macctl |= B43_MACCTL_PSM_JMP0; macctl |= B43_MACCTL_PSM_JMP0;
b43_write32(dev, B43_MMIO_MACCTL, macctl); b43_write32(dev, B43_MMIO_MACCTL, macctl);
if (!dev->suspend_in_progress) {
b43_leds_exit(dev);
b43_rng_exit(dev->wl);
}
b43_dma_free(dev); b43_dma_free(dev);
b43_pio_free(dev); b43_pio_free(dev);
b43_chip_exit(dev); b43_chip_exit(dev);
@ -4180,7 +4263,6 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
/* Initialize a wireless core */ /* Initialize a wireless core */
static int b43_wireless_core_init(struct b43_wldev *dev) static int b43_wireless_core_init(struct b43_wldev *dev)
{ {
struct b43_wl *wl = dev->wl;
struct ssb_bus *bus = dev->dev->bus; struct ssb_bus *bus = dev->dev->bus;
struct ssb_sprom *sprom = &bus->sprom; struct ssb_sprom *sprom = &bus->sprom;
struct b43_phy *phy = &dev->phy; struct b43_phy *phy = &dev->phy;
@ -4264,7 +4346,9 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
/* Maximum Contention Window */ /* Maximum Contention Window */
b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF); b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || B43_FORCE_PIO) { if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) ||
(dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) ||
B43_FORCE_PIO) {
dev->__using_pio_transfers = 1; dev->__using_pio_transfers = 1;
err = b43_pio_init(dev); err = b43_pio_init(dev);
} else { } else {
@ -4280,15 +4364,13 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)); ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW));
b43_upload_card_macaddress(dev); b43_upload_card_macaddress(dev);
b43_security_init(dev); b43_security_init(dev);
if (!dev->suspend_in_progress)
b43_rng_init(wl); ieee80211_wake_queues(dev->wl->hw);
ieee80211_wake_queues(dev->wl->hw); ieee80211_wake_queues(dev->wl->hw);
b43_set_status(dev, B43_STAT_INITIALIZED); b43_set_status(dev, B43_STAT_INITIALIZED);
if (!dev->suspend_in_progress)
b43_leds_init(dev);
out: out:
return err; return err;
@ -4837,7 +4919,6 @@ static int b43_wireless_init(struct ssb_device *dev)
/* Initialize struct b43_wl */ /* Initialize struct b43_wl */
wl->hw = hw; wl->hw = hw;
spin_lock_init(&wl->leds_lock);
mutex_init(&wl->mutex); mutex_init(&wl->mutex);
spin_lock_init(&wl->hardirq_lock); spin_lock_init(&wl->hardirq_lock);
INIT_LIST_HEAD(&wl->devlist); INIT_LIST_HEAD(&wl->devlist);
@ -4878,6 +4959,8 @@ static int b43_probe(struct ssb_device *dev, const struct ssb_device_id *id)
err = ieee80211_register_hw(wl->hw); err = ieee80211_register_hw(wl->hw);
if (err) if (err)
goto err_one_core_detach; goto err_one_core_detach;
b43_leds_register(wl->current_dev);
b43_rng_init(wl);
} }
out: out:
@ -4906,12 +4989,15 @@ static void b43_remove(struct ssb_device *dev)
* might have modified it. Restoring is important, so the networking * might have modified it. Restoring is important, so the networking
* stack can properly free resources. */ * stack can properly free resources. */
wl->hw->queues = wl->mac80211_initially_registered_queues; wl->hw->queues = wl->mac80211_initially_registered_queues;
b43_leds_stop(wldev);
ieee80211_unregister_hw(wl->hw); ieee80211_unregister_hw(wl->hw);
} }
b43_one_core_detach(dev); b43_one_core_detach(dev);
if (list_empty(&wl->devlist)) { if (list_empty(&wl->devlist)) {
b43_rng_exit(wl);
b43_leds_unregister(wldev);
/* Last core on the chip unregistered. /* Last core on the chip unregistered.
* We can destroy common struct b43_wl. * We can destroy common struct b43_wl.
*/ */
@ -4929,80 +5015,17 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason)
ieee80211_queue_work(dev->wl->hw, &dev->restart_work); ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
} }
#ifdef CONFIG_PM
static int b43_suspend(struct ssb_device *dev, pm_message_t state)
{
struct b43_wldev *wldev = ssb_get_drvdata(dev);
struct b43_wl *wl = wldev->wl;
b43dbg(wl, "Suspending...\n");
mutex_lock(&wl->mutex);
wldev->suspend_in_progress = true;
wldev->suspend_init_status = b43_status(wldev);
if (wldev->suspend_init_status >= B43_STAT_STARTED)
wldev = b43_wireless_core_stop(wldev);
if (wldev && wldev->suspend_init_status >= B43_STAT_INITIALIZED)
b43_wireless_core_exit(wldev);
mutex_unlock(&wl->mutex);
b43dbg(wl, "Device suspended.\n");
return 0;
}
static int b43_resume(struct ssb_device *dev)
{
struct b43_wldev *wldev = ssb_get_drvdata(dev);
struct b43_wl *wl = wldev->wl;
int err = 0;
b43dbg(wl, "Resuming...\n");
mutex_lock(&wl->mutex);
if (wldev->suspend_init_status >= B43_STAT_INITIALIZED) {
err = b43_wireless_core_init(wldev);
if (err) {
b43err(wl, "Resume failed at core init\n");
goto out;
}
}
if (wldev->suspend_init_status >= B43_STAT_STARTED) {
err = b43_wireless_core_start(wldev);
if (err) {
b43_leds_exit(wldev);
b43_rng_exit(wldev->wl);
b43_wireless_core_exit(wldev);
b43err(wl, "Resume failed at core start\n");
goto out;
}
}
b43dbg(wl, "Device resumed.\n");
out:
wldev->suspend_in_progress = false;
mutex_unlock(&wl->mutex);
return err;
}
#else /* CONFIG_PM */
# define b43_suspend NULL
# define b43_resume NULL
#endif /* CONFIG_PM */
static struct ssb_driver b43_ssb_driver = { static struct ssb_driver b43_ssb_driver = {
.name = KBUILD_MODNAME, .name = KBUILD_MODNAME,
.id_table = b43_ssb_tbl, .id_table = b43_ssb_tbl,
.probe = b43_probe, .probe = b43_probe,
.remove = b43_remove, .remove = b43_remove,
.suspend = b43_suspend,
.resume = b43_resume,
}; };
static void b43_print_driverinfo(void) static void b43_print_driverinfo(void)
{ {
const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "", const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "",
*feat_leds = ""; *feat_leds = "", *feat_sdio = "";
#ifdef CONFIG_B43_PCI_AUTOSELECT #ifdef CONFIG_B43_PCI_AUTOSELECT
feat_pci = "P"; feat_pci = "P";
@ -5015,12 +5038,15 @@ static void b43_print_driverinfo(void)
#endif #endif
#ifdef CONFIG_B43_LEDS #ifdef CONFIG_B43_LEDS
feat_leds = "L"; feat_leds = "L";
#endif
#ifdef CONFIG_B43_SDIO
feat_sdio = "S";
#endif #endif
printk(KERN_INFO "Broadcom 43xx driver loaded " printk(KERN_INFO "Broadcom 43xx driver loaded "
"[ Features: %s%s%s%s, Firmware-ID: " "[ Features: %s%s%s%s%s, Firmware-ID: "
B43_SUPPORTED_FIRMWARE_ID " ]\n", B43_SUPPORTED_FIRMWARE_ID " ]\n",
feat_pci, feat_pcmcia, feat_nphy, feat_pci, feat_pcmcia, feat_nphy,
feat_leds); feat_leds, feat_sdio);
} }
static int __init b43_init(void) static int __init b43_init(void)
@ -5031,13 +5057,18 @@ static int __init b43_init(void)
err = b43_pcmcia_init(); err = b43_pcmcia_init();
if (err) if (err)
goto err_dfs_exit; goto err_dfs_exit;
err = ssb_driver_register(&b43_ssb_driver); err = b43_sdio_init();
if (err) if (err)
goto err_pcmcia_exit; goto err_pcmcia_exit;
err = ssb_driver_register(&b43_ssb_driver);
if (err)
goto err_sdio_exit;
b43_print_driverinfo(); b43_print_driverinfo();
return err; return err;
err_sdio_exit:
b43_sdio_exit();
err_pcmcia_exit: err_pcmcia_exit:
b43_pcmcia_exit(); b43_pcmcia_exit();
err_dfs_exit: err_dfs_exit:
@ -5048,6 +5079,7 @@ err_dfs_exit:
static void __exit b43_exit(void) static void __exit b43_exit(void)
{ {
ssb_driver_unregister(&b43_ssb_driver); ssb_driver_unregister(&b43_ssb_driver);
b43_sdio_exit();
b43_pcmcia_exit(); b43_pcmcia_exit();
b43_debugfs_exit(); b43_debugfs_exit();
} }

View file

@ -2228,6 +2228,16 @@ static enum b43_txpwr_result b43_lpphy_op_recalc_txpower(struct b43_wldev *dev,
return B43_TXPWR_RES_DONE; return B43_TXPWR_RES_DONE;
} }
void b43_lpphy_op_switch_analog(struct b43_wldev *dev, bool on)
{
if (on) {
b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xfff8);
} else {
b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0x0007);
b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 0x0007);
}
}
const struct b43_phy_operations b43_phyops_lp = { const struct b43_phy_operations b43_phyops_lp = {
.allocate = b43_lpphy_op_allocate, .allocate = b43_lpphy_op_allocate,
.free = b43_lpphy_op_free, .free = b43_lpphy_op_free,
@ -2239,7 +2249,7 @@ const struct b43_phy_operations b43_phyops_lp = {
.radio_read = b43_lpphy_op_radio_read, .radio_read = b43_lpphy_op_radio_read,
.radio_write = b43_lpphy_op_radio_write, .radio_write = b43_lpphy_op_radio_write,
.software_rfkill = b43_lpphy_op_software_rfkill, .software_rfkill = b43_lpphy_op_software_rfkill,
.switch_analog = b43_phyop_switch_analog_generic, .switch_analog = b43_lpphy_op_switch_analog,
.switch_channel = b43_lpphy_op_switch_channel, .switch_channel = b43_lpphy_op_switch_channel,
.get_default_chan = b43_lpphy_op_get_default_chan, .get_default_chan = b43_lpphy_op_get_default_chan,
.set_rx_antenna = b43_lpphy_op_set_rx_antenna, .set_rx_antenna = b43_lpphy_op_set_rx_antenna,

View file

@ -574,7 +574,7 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev,
q->buffer_used -= total_len; q->buffer_used -= total_len;
q->free_packet_slots += 1; q->free_packet_slots += 1;
ieee80211_tx_status_irqsafe(dev->wl->hw, pack->skb); ieee80211_tx_status(dev->wl->hw, pack->skb);
pack->skb = NULL; pack->skb = NULL;
list_add(&pack->list, &q->packets_list); list_add(&pack->list, &q->packets_list);

View file

@ -28,7 +28,7 @@
/* Returns TRUE, if the radio is enabled in hardware. */ /* Returns TRUE, if the radio is enabled in hardware. */
bool b43_is_hw_radio_enabled(struct b43_wldev *dev) bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
{ {
if (dev->phy.rev >= 3) { if (dev->phy.rev >= 3 || dev->phy.type == B43_PHYTYPE_LP) {
if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI) if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI)
& B43_MMIO_RADIO_HWENABLED_HI_MASK)) & B43_MMIO_RADIO_HWENABLED_HI_MASK))
return 1; return 1;

View file

@ -0,0 +1,202 @@
/*
* Broadcom B43 wireless driver
*
* SDIO over Sonics Silicon Backplane bus glue for b43.
*
* Copyright (C) 2009 Albert Herranz
* Copyright (C) 2009 Michael Buesch <mb@bu3sch.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*/
#include <linux/kernel.h>
#include <linux/mmc/card.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/ssb/ssb.h>
#include "sdio.h"
#include "b43.h"
#define HNBU_CHIPID 0x01 /* vendor & device id */
#define B43_SDIO_BLOCK_SIZE 64 /* rx fifo max size in bytes */
static const struct b43_sdio_quirk {
u16 vendor;
u16 device;
unsigned int quirks;
} b43_sdio_quirks[] = {
{ 0x14E4, 0x4318, SSB_QUIRK_SDIO_READ_AFTER_WRITE32, },
{ },
};
static unsigned int b43_sdio_get_quirks(u16 vendor, u16 device)
{
const struct b43_sdio_quirk *q;
for (q = b43_sdio_quirks; q->quirks; q++) {
if (vendor == q->vendor && device == q->device)
return q->quirks;
}
return 0;
}
static void b43_sdio_interrupt_dispatcher(struct sdio_func *func)
{
struct b43_sdio *sdio = sdio_get_drvdata(func);
struct b43_wldev *dev = sdio->irq_handler_opaque;
if (unlikely(b43_status(dev) < B43_STAT_STARTED))
return;
sdio_release_host(func);
sdio->irq_handler(dev);
sdio_claim_host(func);
}
int b43_sdio_request_irq(struct b43_wldev *dev,
void (*handler)(struct b43_wldev *dev))
{
struct ssb_bus *bus = dev->dev->bus;
struct sdio_func *func = bus->host_sdio;
struct b43_sdio *sdio = sdio_get_drvdata(func);
int err;
sdio->irq_handler_opaque = dev;
sdio->irq_handler = handler;
sdio_claim_host(func);
err = sdio_claim_irq(func, b43_sdio_interrupt_dispatcher);
sdio_release_host(func);
return err;
}
void b43_sdio_free_irq(struct b43_wldev *dev)
{
struct ssb_bus *bus = dev->dev->bus;
struct sdio_func *func = bus->host_sdio;
struct b43_sdio *sdio = sdio_get_drvdata(func);
sdio_claim_host(func);
sdio_release_irq(func);
sdio_release_host(func);
sdio->irq_handler_opaque = NULL;
sdio->irq_handler = NULL;
}
static int b43_sdio_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
struct b43_sdio *sdio;
struct sdio_func_tuple *tuple;
u16 vendor = 0, device = 0;
int error;
/* Look for the card chip identifier. */
tuple = func->tuples;
while (tuple) {
switch (tuple->code) {
case 0x80:
switch (tuple->data[0]) {
case HNBU_CHIPID:
if (tuple->size != 5)
break;
vendor = tuple->data[1] | (tuple->data[2]<<8);
device = tuple->data[3] | (tuple->data[4]<<8);
dev_info(&func->dev, "Chip ID %04x:%04x\n",
vendor, device);
break;
default:
break;
}
break;
default:
break;
}
tuple = tuple->next;
}
if (!vendor || !device) {
error = -ENODEV;
goto out;
}
sdio_claim_host(func);
error = sdio_set_block_size(func, B43_SDIO_BLOCK_SIZE);
if (error) {
dev_err(&func->dev, "failed to set block size to %u bytes,"
" error %d\n", B43_SDIO_BLOCK_SIZE, error);
goto err_release_host;
}
error = sdio_enable_func(func);
if (error) {
dev_err(&func->dev, "failed to enable func, error %d\n", error);
goto err_release_host;
}
sdio_release_host(func);
sdio = kzalloc(sizeof(*sdio), GFP_KERNEL);
if (!sdio) {
error = -ENOMEM;
dev_err(&func->dev, "failed to allocate ssb bus\n");
goto err_disable_func;
}
error = ssb_bus_sdiobus_register(&sdio->ssb, func,
b43_sdio_get_quirks(vendor, device));
if (error) {
dev_err(&func->dev, "failed to register ssb sdio bus,"
" error %d\n", error);
goto err_free_ssb;
}
sdio_set_drvdata(func, sdio);
return 0;
err_free_ssb:
kfree(sdio);
err_disable_func:
sdio_disable_func(func);
err_release_host:
sdio_release_host(func);
out:
return error;
}
static void b43_sdio_remove(struct sdio_func *func)
{
struct b43_sdio *sdio = sdio_get_drvdata(func);
ssb_bus_unregister(&sdio->ssb);
sdio_disable_func(func);
kfree(sdio);
sdio_set_drvdata(func, NULL);
}
static const struct sdio_device_id b43_sdio_ids[] = {
{ SDIO_DEVICE(0x02d0, 0x044b) }, /* Nintendo Wii WLAN daughter card */
{ },
};
static struct sdio_driver b43_sdio_driver = {
.name = "b43-sdio",
.id_table = b43_sdio_ids,
.probe = b43_sdio_probe,
.remove = b43_sdio_remove,
};
int b43_sdio_init(void)
{
return sdio_register_driver(&b43_sdio_driver);
}
void b43_sdio_exit(void)
{
sdio_unregister_driver(&b43_sdio_driver);
}

View file

@ -0,0 +1,45 @@
#ifndef B43_SDIO_H_
#define B43_SDIO_H_
#include <linux/ssb/ssb.h>
struct b43_wldev;
#ifdef CONFIG_B43_SDIO
struct b43_sdio {
struct ssb_bus ssb;
void *irq_handler_opaque;
void (*irq_handler)(struct b43_wldev *dev);
};
int b43_sdio_request_irq(struct b43_wldev *dev,
void (*handler)(struct b43_wldev *dev));
void b43_sdio_free_irq(struct b43_wldev *dev);
int b43_sdio_init(void);
void b43_sdio_exit(void);
#else /* CONFIG_B43_SDIO */
int b43_sdio_request_irq(struct b43_wldev *dev,
void (*handler)(struct b43_wldev *dev))
{
return -ENODEV;
}
void b43_sdio_free_irq(struct b43_wldev *dev)
{
}
static inline int b43_sdio_init(void)
{
return 0;
}
static inline void b43_sdio_exit(void)
{
}
#endif /* CONFIG_B43_SDIO */
#endif /* B43_SDIO_H_ */

View file

@ -690,8 +690,11 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
} }
memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
ieee80211_rx_irqsafe(dev->wl->hw, skb); ieee80211_rx(dev->wl->hw, skb);
#if B43_DEBUG
dev->rx_count++;
#endif
return; return;
drop: drop:
b43dbg(dev->wl, "RX: Packet dropped\n"); b43dbg(dev->wl, "RX: Packet dropped\n");

View file

@ -2021,6 +2021,12 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
agg->frame_count, txq_id, idx); agg->frame_count, txq_id, idx);
hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
if (!hdr) {
IWL_ERR(priv,
"BUG_ON idx doesn't point to valid skb"
" idx=%d, txq_id=%d\n", idx, txq_id);
return -1;
}
sc = le16_to_cpu(hdr->seq_ctrl); sc = le16_to_cpu(hdr->seq_ctrl);
if (idx != (SEQ_TO_SN(sc) & 0xff)) { if (idx != (SEQ_TO_SN(sc) & 0xff)) {

View file

@ -1163,6 +1163,12 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv,
agg->frame_count, txq_id, idx); agg->frame_count, txq_id, idx);
hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
if (!hdr) {
IWL_ERR(priv,
"BUG_ON idx doesn't point to valid skb"
" idx=%d, txq_id=%d\n", idx, txq_id);
return -1;
}
sc = le16_to_cpu(hdr->seq_ctrl); sc = le16_to_cpu(hdr->seq_ctrl);
if (idx != (SEQ_TO_SN(sc) & 0xff)) { if (idx != (SEQ_TO_SN(sc) & 0xff)) {

View file

@ -250,12 +250,20 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
} }
spin_unlock_irqrestore(&rxq->lock, flags); spin_unlock_irqrestore(&rxq->lock, flags);
if (rxq->free_count > RX_LOW_WATERMARK)
priority |= __GFP_NOWARN;
/* Alloc a new receive buffer */ /* Alloc a new receive buffer */
skb = alloc_skb(priv->hw_params.rx_buf_size + 256, skb = alloc_skb(priv->hw_params.rx_buf_size + 256,
priority); priority);
if (!skb) { if (!skb) {
IWL_CRIT(priv, "Can not allocate SKB buffers\n"); if (net_ratelimit())
IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
if ((rxq->free_count <= RX_LOW_WATERMARK) &&
net_ratelimit())
IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n",
priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL",
rxq->free_count);
/* We don't reschedule replenish work here -- we will /* We don't reschedule replenish work here -- we will
* call the restock method and if it still needs * call the restock method and if it still needs
* more buffers it will schedule replenish */ * more buffers it will schedule replenish */

View file

@ -520,7 +520,7 @@ int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
struct iwl_host_cmd cmd = { struct iwl_host_cmd cmd = {
.id = REPLY_WEPKEY, .id = REPLY_WEPKEY,
.data = wep_cmd, .data = wep_cmd,
.flags = CMD_SYNC, .flags = CMD_ASYNC,
}; };
memset(wep_cmd, 0, cmd_size + memset(wep_cmd, 0, cmd_size +

View file

@ -1146,11 +1146,18 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
} }
spin_unlock_irqrestore(&rxq->lock, flags); spin_unlock_irqrestore(&rxq->lock, flags);
if (rxq->free_count > RX_LOW_WATERMARK)
priority |= __GFP_NOWARN;
/* Alloc a new receive buffer */ /* Alloc a new receive buffer */
skb = alloc_skb(priv->hw_params.rx_buf_size, priority); skb = alloc_skb(priv->hw_params.rx_buf_size, priority);
if (!skb) { if (!skb) {
if (net_ratelimit()) if (net_ratelimit())
IWL_CRIT(priv, ": Can not allocate SKB buffers\n"); IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
if ((rxq->free_count <= RX_LOW_WATERMARK) &&
net_ratelimit())
IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n",
priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL",
rxq->free_count);
/* We don't reschedule replenish work here -- we will /* We don't reschedule replenish work here -- we will
* call the restock method and if it still needs * call the restock method and if it still needs
* more buffers it will schedule replenish */ * more buffers it will schedule replenish */

View file

@ -380,7 +380,7 @@ static inline void rt2x00crypto_tx_insert_iv(struct sk_buff *skb,
{ {
} }
static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad, static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
unsigned int header_length, unsigned int header_length,
struct rxdone_entry_desc *rxdesc) struct rxdone_entry_desc *rxdesc)
{ {

View file

@ -1,5 +1,5 @@
menuconfig WL12XX menuconfig WL12XX
boolean "TI wl12xx driver support" tristate "TI wl12xx driver support"
depends on MAC80211 && WLAN_80211 && EXPERIMENTAL depends on MAC80211 && WLAN_80211 && EXPERIMENTAL
---help--- ---help---
This will enable TI wl12xx driver support. The drivers make This will enable TI wl12xx driver support. The drivers make

View file

@ -1070,7 +1070,7 @@ static int eject_installer(struct usb_interface *intf)
/* Find bulk out endpoint */ /* Find bulk out endpoint */
endpoint = &iface_desc->endpoint[1].desc; endpoint = &iface_desc->endpoint[1].desc;
if ((endpoint->bEndpointAddress & USB_TYPE_MASK) == USB_DIR_OUT && if (usb_endpoint_dir_out(endpoint) &&
usb_endpoint_xfer_bulk(endpoint)) { usb_endpoint_xfer_bulk(endpoint)) {
bulk_out_ep = endpoint->bEndpointAddress; bulk_out_ep = endpoint->bEndpointAddress;
} else { } else {

View file

@ -134,18 +134,15 @@ static void xemaclite_enable_interrupts(struct net_local *drvdata)
} }
/* Enable the Rx interrupts for the first buffer */ /* Enable the Rx interrupts for the first buffer */
reg_data = in_be32(drvdata->base_addr + XEL_RSR_OFFSET);
out_be32(drvdata->base_addr + XEL_RSR_OFFSET, out_be32(drvdata->base_addr + XEL_RSR_OFFSET,
reg_data | XEL_RSR_RECV_IE_MASK); XEL_RSR_RECV_IE_MASK);
/* Enable the Rx interrupts for the second Buffer if /* Enable the Rx interrupts for the second Buffer if
* configured in HW */ * configured in HW */
if (drvdata->rx_ping_pong != 0) { if (drvdata->rx_ping_pong != 0) {
reg_data = in_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
XEL_RSR_OFFSET);
out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET + out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
XEL_RSR_OFFSET, XEL_RSR_OFFSET,
reg_data | XEL_RSR_RECV_IE_MASK); XEL_RSR_RECV_IE_MASK);
} }
/* Enable the Global Interrupt Enable */ /* Enable the Global Interrupt Enable */

View file

@ -117,8 +117,6 @@ source "drivers/staging/vt6655/Kconfig"
source "drivers/staging/vt6656/Kconfig" source "drivers/staging/vt6656/Kconfig"
source "drivers/staging/cpc-usb/Kconfig"
source "drivers/staging/udlfb/Kconfig" source "drivers/staging/udlfb/Kconfig"
source "drivers/staging/hv/Kconfig" source "drivers/staging/hv/Kconfig"

View file

@ -40,7 +40,6 @@ obj-$(CONFIG_USB_SERIAL_QUATECH_USB2) += quatech_usb2/
obj-$(CONFIG_OCTEON_ETHERNET) += octeon/ obj-$(CONFIG_OCTEON_ETHERNET) += octeon/
obj-$(CONFIG_VT6655) += vt6655/ obj-$(CONFIG_VT6655) += vt6655/
obj-$(CONFIG_VT6656) += vt6656/ obj-$(CONFIG_VT6656) += vt6656/
obj-$(CONFIG_USB_CPC) += cpc-usb/
obj-$(CONFIG_FB_UDL) += udlfb/ obj-$(CONFIG_FB_UDL) += udlfb/
obj-$(CONFIG_HYPERV) += hv/ obj-$(CONFIG_HYPERV) += hv/
obj-$(CONFIG_VME_BUS) += vme/ obj-$(CONFIG_VME_BUS) += vme/

View file

@ -1,4 +0,0 @@
config USB_CPC
tristate "CPC CAN USB driver"
depends on USB && PROC_FS
default n

View file

@ -1,3 +0,0 @@
obj-$(CONFIG_USB_CPC) += cpc-usb.o
cpc-usb-y := cpc-usb_drv.o sja2m16c_2.o

View file

@ -1,10 +0,0 @@
Things to do for this driver to get merged into the main portion of the
kernel:
- checkpatch cleanups
- sparse clean
- remove proc code
- tie into CAN socket interfaces if possible
- figure out sane userspace api
- use linux's error codes
Send patches to Greg Kroah-Hartman <greg@kroah.com>

File diff suppressed because it is too large Load diff

View file

@ -1,417 +0,0 @@
/*
* CPC CAN Interface Definitions
*
* Copyright (C) 2000-2008 EMS Dr. Thomas Wuensche
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef CPC_HEADER
#define CPC_HEADER
/*
* the maximum length of the union members within a CPC_MSG
* this value can be defined by the customer, but has to be
* >= 64 bytes
* however, if not defined before, we set a length of 64 byte
*/
#if !defined(CPC_MSG_LEN) || (CPC_MSG_LEN < 64)
#undef CPC_MSG_LEN
#define CPC_MSG_LEN 64
#endif
/*
* Transmission of events from CPC interfaces to PC can be individually
* controlled per event type. Default state is: don't transmit
* Control values are constructed by bit-or of Subject and Action
* and passed to CPC_Control()
*/
/* Control-Values for CPC_Control() Command Subject Selection */
#define CONTR_CAN_Message 0x04
#define CONTR_Busload 0x08
#define CONTR_CAN_State 0x0C
#define CONTR_SendAck 0x10
#define CONTR_Filter 0x14
#define CONTR_CmdQueue 0x18 /* reserved, do not use */
#define CONTR_BusError 0x1C
/* Control Command Actions */
#define CONTR_CONT_OFF 0
#define CONTR_CONT_ON 1
#define CONTR_SING_ON 2
/*
* CONTR_SING_ON doesn't change CONTR_CONT_ON state, so it should be
* read as: transmit at least once
*/
/* defines for confirmed request */
#define DO_NOT_CONFIRM 0
#define DO_CONFIRM 1
/* event flags */
#define EVENT_READ 0x01
#define EVENT_WRITE 0x02
/*
* Messages from CPC to PC contain a message object type field.
* The following message types are sent by CPC and can be used in
* handlers, others should be ignored.
*/
#define CPC_MSG_T_RESYNC 0 /* Normally to be ignored */
#define CPC_MSG_T_CAN 1 /* CAN data frame */
#define CPC_MSG_T_BUSLOAD 2 /* Busload message */
#define CPC_MSG_T_STRING 3 /* Normally to be ignored */
#define CPC_MSG_T_CONTI 4 /* Normally to be ignored */
#define CPC_MSG_T_MEM 7 /* Normally not to be handled */
#define CPC_MSG_T_RTR 8 /* CAN remote frame */
#define CPC_MSG_T_TXACK 9 /* Send acknowledge */
#define CPC_MSG_T_POWERUP 10 /* Power-up message */
#define CPC_MSG_T_CMD_NO 11 /* Normally to be ignored */
#define CPC_MSG_T_CAN_PRMS 12 /* Actual CAN parameters */
#define CPC_MSG_T_ABORTED 13 /* Command aborted message */
#define CPC_MSG_T_CANSTATE 14 /* CAN state message */
#define CPC_MSG_T_RESET 15 /* used to reset CAN-Controller */
#define CPC_MSG_T_XCAN 16 /* XCAN data frame */
#define CPC_MSG_T_XRTR 17 /* XCAN remote frame */
#define CPC_MSG_T_INFO 18 /* information strings */
#define CPC_MSG_T_CONTROL 19 /* used for control of interface/driver behaviour */
#define CPC_MSG_T_CONFIRM 20 /* response type for confirmed requests */
#define CPC_MSG_T_OVERRUN 21 /* response type for overrun conditions */
#define CPC_MSG_T_KEEPALIVE 22 /* response type for keep alive conditions */
#define CPC_MSG_T_CANERROR 23 /* response type for bus error conditions */
#define CPC_MSG_T_DISCONNECTED 24 /* response type for a disconnected interface */
#define CPC_MSG_T_ERR_COUNTER 25 /* RX/TX error counter of CAN controller */
#define CPC_MSG_T_FIRMWARE 100 /* response type for USB firmware download */
/*
* Messages from the PC to the CPC interface contain a command field
* Most of the command types are wrapped by the library functions and have therefore
* normally not to be used.
* However, programmers who wish to circumvent the library and talk directly
* to the drivers (mainly Linux programmers) can use the following
* command types:
*/
#define CPC_CMD_T_CAN 1 /* CAN data frame */
#define CPC_CMD_T_CONTROL 3 /* used for control of interface/driver behaviour */
#define CPC_CMD_T_CAN_PRMS 6 /* set CAN parameters */
#define CPC_CMD_T_CLEARBUF 8 /* clears input queue; this is depricated, use CPC_CMD_T_CLEAR_MSG_QUEUE instead */
#define CPC_CMD_T_INQ_CAN_PARMS 11 /* inquire actual CAN parameters */
#define CPC_CMD_T_FILTER_PRMS 12 /* set filter parameter */
#define CPC_CMD_T_RTR 13 /* CAN remote frame */
#define CPC_CMD_T_CANSTATE 14 /* CAN state message */
#define CPC_CMD_T_XCAN 15 /* XCAN data frame */
#define CPC_CMD_T_XRTR 16 /* XCAN remote frame */
#define CPC_CMD_T_RESET 17 /* used to reset CAN-Controller */
#define CPC_CMD_T_INQ_INFO 18 /* miscellanous information strings */
#define CPC_CMD_T_OPEN_CHAN 19 /* open a channel */
#define CPC_CMD_T_CLOSE_CHAN 20 /* close a channel */
#define CPC_CMD_T_CNTBUF 21 /* this is depricated, use CPC_CMD_T_INQ_MSG_QUEUE_CNT instead */
#define CPC_CMD_T_CAN_EXIT 200 /* exit the CAN (disable interrupts; reset bootrate; reset output_cntr; mode = 1) */
#define CPC_CMD_T_INQ_MSG_QUEUE_CNT CPC_CMD_T_CNTBUF /* inquires the count of elements in the message queue */
#define CPC_CMD_T_INQ_ERR_COUNTER 25 /* request the CAN controllers error counter */
#define CPC_CMD_T_CLEAR_MSG_QUEUE CPC_CMD_T_CLEARBUF /* clear CPC_MSG queue */
#define CPC_CMD_T_CLEAR_CMD_QUEUE 28 /* clear CPC_CMD queue */
#define CPC_CMD_T_FIRMWARE 100 /* reserved, must not be used */
#define CPC_CMD_T_USB_RESET 101 /* reserved, must not be used */
#define CPC_CMD_T_WAIT_NOTIFY 102 /* reserved, must not be used */
#define CPC_CMD_T_WAIT_SETUP 103 /* reserved, must not be used */
#define CPC_CMD_T_ABORT 255 /* Normally not to be used */
/* definitions for CPC_MSG_T_INFO information sources */
#define CPC_INFOMSG_T_UNKNOWN_SOURCE 0
#define CPC_INFOMSG_T_INTERFACE 1
#define CPC_INFOMSG_T_DRIVER 2
#define CPC_INFOMSG_T_LIBRARY 3
/* information types */
#define CPC_INFOMSG_T_UNKNOWN_TYPE 0
#define CPC_INFOMSG_T_VERSION 1
#define CPC_INFOMSG_T_SERIAL 2
/* definitions for controller types */
#define PCA82C200 1 /* Philips basic CAN controller, replaced by SJA1000 */
#define SJA1000 2 /* Philips basic CAN controller */
#define AN82527 3 /* Intel full CAN controller */
#define M16C_BASIC 4 /* M16C controller running in basic CAN (not full CAN) mode */
/* channel open error codes */
#define CPC_ERR_NO_FREE_CHANNEL -1 /* no more free space within the channel array */
#define CPC_ERR_CHANNEL_ALREADY_OPEN -2 /* the channel is already open */
#define CPC_ERR_CHANNEL_NOT_ACTIVE -3 /* access to a channel not active failed */
#define CPC_ERR_NO_DRIVER_PRESENT -4 /* no driver at the location searched by the library */
#define CPC_ERR_NO_INIFILE_PRESENT -5 /* the library could not find the inifile */
#define CPC_ERR_WRONG_PARAMETERS -6 /* wrong parameters in the inifile */
#define CPC_ERR_NO_INTERFACE_PRESENT -7 /* 1. The specified interface is not connected */
/* 2. The interface (mostly CPC-USB) was disconnected upon operation */
#define CPC_ERR_NO_MATCHING_CHANNEL -8 /* the driver couldn't find a matching channel */
#define CPC_ERR_NO_BUFFER_AVAILABLE -9 /* the driver couldn't allocate buffer for messages */
#define CPC_ERR_NO_INTERRUPT -10 /* the requested interrupt couldn't be claimed */
#define CPC_ERR_NO_MATCHING_INTERFACE -11 /* no interface type related to this channel was found */
#define CPC_ERR_NO_RESOURCES -12 /* the requested resources could not be claimed */
#define CPC_ERR_SOCKET -13 /* error concerning TCP sockets */
/* init error codes */
#define CPC_ERR_WRONG_CONTROLLER_TYPE -14 /* wrong CAN controller type within initialization */
#define CPC_ERR_NO_RESET_MODE -15 /* the controller could not be set into reset mode */
#define CPC_ERR_NO_CAN_ACCESS -16 /* the CAN controller could not be accessed */
/* transmit error codes */
#define CPC_ERR_CAN_WRONG_ID -20 /* the provided CAN id is too big */
#define CPC_ERR_CAN_WRONG_LENGTH -21 /* the provided CAN length is too long */
#define CPC_ERR_CAN_NO_TRANSMIT_BUF -22 /* the transmit buffer was occupied */
#define CPC_ERR_CAN_TRANSMIT_TIMEOUT -23 /* The message could not be sent within a */
/* specified time */
/* other error codes */
#define CPC_ERR_SERVICE_NOT_SUPPORTED -30 /* the requested service is not supported by the interface */
#define CPC_ERR_IO_TRANSFER -31 /* a transmission error down to the driver occurred */
#define CPC_ERR_TRANSMISSION_FAILED -32 /* a transmission error down to the interface occurred */
#define CPC_ERR_TRANSMISSION_TIMEOUT -33 /* a timeout occurred within transmission to the interface */
#define CPC_ERR_OP_SYS_NOT_SUPPORTED -35 /* the operating system is not supported */
#define CPC_ERR_UNKNOWN -40 /* an unknown error ocurred (mostly IOCTL errors) */
#define CPC_ERR_LOADING_DLL -50 /* the library 'cpcwin.dll' could not be loaded */
#define CPC_ERR_ASSIGNING_FUNCTION -51 /* the specified function could not be assigned */
#define CPC_ERR_DLL_INITIALIZATION -52 /* the DLL was not initialized correctly */
#define CPC_ERR_MISSING_LICFILE -55 /* the file containing the licenses does not exist */
#define CPC_ERR_MISSING_LICENSE -56 /* a required license was not found */
/* CAN state bit values. Ignore any bits not listed */
#define CPC_CAN_STATE_BUSOFF 0x80
#define CPC_CAN_STATE_ERROR 0x40
/* Mask to help ignore undefined bits */
#define CPC_CAN_STATE_MASK 0xc0
/*
* CAN-Message representation in a CPC_MS
* Message object type is CPC_MSG_T_CAN or CPC_MSG_T_RTR
* or CPC_MSG_T_XCAN or CPC_MSG_T_XRTR
*/
typedef struct CPC_CAN_MSG {
u32 id;
u8 length;
u8 msg[8];
} CPC_CAN_MSG_T;
/* representation of the CAN parameters for the PCA82C200 controller */
typedef struct CPC_PCA82C200_PARAMS {
u8 acc_code; /* Acceptance-code for receive, Standard: 0 */
u8 acc_mask; /* Acceptance-mask for receive, Standard: 0xff (everything) */
u8 btr0; /* Bus-timing register 0 */
u8 btr1; /* Bus-timing register 1 */
u8 outp_contr; /* Output-control register */
} CPC_PCA82C200_PARAMS_T;
/* representation of the CAN parameters for the SJA1000 controller */
typedef struct CPC_SJA1000_PARAMS {
u8 mode; /* enables single or dual acceptance filtering */
u8 acc_code0; /* Acceptance-code for receive, Standard: 0 */
u8 acc_code1;
u8 acc_code2;
u8 acc_code3;
u8 acc_mask0; /* Acceptance-mask for receive, Standard: 0xff (everything) */
u8 acc_mask1;
u8 acc_mask2;
u8 acc_mask3;
u8 btr0; /* Bus-timing register 0 */
u8 btr1; /* Bus-timing register 1 */
u8 outp_contr; /* Output-control register */
} CPC_SJA1000_PARAMS_T;
/*
* representation of the CAN parameters for the M16C controller
* in basic CAN mode (means no full CAN)
*/
typedef struct CPC_M16C_BASIC_PARAMS {
u8 con0;
u8 con1;
u8 ctlr0;
u8 ctlr1;
u8 clk;
u8 acc_std_code0;
u8 acc_std_code1;
u8 acc_ext_code0;
u8 acc_ext_code1;
u8 acc_ext_code2;
u8 acc_ext_code3;
u8 acc_std_mask0;
u8 acc_std_mask1;
u8 acc_ext_mask0;
u8 acc_ext_mask1;
u8 acc_ext_mask2;
u8 acc_ext_mask3;
} CPC_M16C_BASIC_PARAMS_T;
/* CAN params message representation */
typedef struct CPC_CAN_PARAMS {
u8 cc_type; /* represents the controller type */
union {
CPC_M16C_BASIC_PARAMS_T m16c_basic;
CPC_SJA1000_PARAMS_T sja1000;
CPC_PCA82C200_PARAMS_T pca82c200;
} cc_params;
} CPC_CAN_PARAMS_T;
/* CHAN init params representation */
typedef struct CPC_CHAN_PARAMS {
int fd;
} CPC_CHAN_PARAMS_T;
/* CAN init params message representation */
typedef struct CPC_INIT_PARAMS {
CPC_CHAN_PARAMS_T chanparams;
CPC_CAN_PARAMS_T canparams;
} CPC_INIT_PARAMS_T;
/* structure for confirmed message handling */
typedef struct CPC_CONFIRM {
u8 result; /* error code */
} CPC_CONFIRM_T;
/* structure for information requests */
typedef struct CPC_INFO {
u8 source; /* interface, driver or library */
u8 type; /* version or serial number */
char msg[CPC_MSG_LEN - 2]; /* string holding the requested information */
} CPC_INFO_T;
/*
* OVERRUN
* In general two types of overrun may occur.
* A hardware overrun, where the CAN controller
* lost a message, because the interrupt was
* not handled before the next messgae comes in.
* Or a software overrun, where i.e. a received
* message could not be stored in the CPC_MSG
* buffer.
*/
/* After a software overrun has occurred
* we wait until we have CPC_OVR_GAP slots
* free in the CPC_MSG buffer.
*/
#define CPC_OVR_GAP 10
/*
* Two types of software overrun may occur.
* A received CAN message or a CAN state event
* can cause an overrun.
* Note: A CPC_CMD which would normally store
* its result immediately in the CPC_MSG
* queue may fail, because the message queue is full.
* This will not generate an overrun message, but
* will halt command execution, until this command
* is able to store its message in the message queue.
*/
#define CPC_OVR_EVENT_CAN 0x01
#define CPC_OVR_EVENT_CANSTATE 0x02
#define CPC_OVR_EVENT_BUSERROR 0x04
/*
* If the CAN controller lost a message
* we indicate it with the highest bit
* set in the count field.
*/
#define CPC_OVR_HW 0x80
/* structure for overrun conditions */
typedef struct {
u8 event;
u8 count;
} CPC_OVERRUN_T;
/*
* CAN errors
* Each CAN controller type has different
* registers to record errors.
* Therefor a structure containing the specific
* errors is set up for each controller here
*/
/*
* SJA1000 error structure
* see the SJA1000 datasheet for detailed
* explanation of the registers
*/
typedef struct CPC_SJA1000_CAN_ERROR {
u8 ecc; /* error capture code register */
u8 rxerr; /* RX error counter register */
u8 txerr; /* TX error counter register */
} CPC_SJA1000_CAN_ERROR_T;
/*
* M16C error structure
* see the M16C datasheet for detailed
* explanation of the registers
*/
typedef struct CPC_M16C_CAN_ERROR {
u8 tbd; /* to be defined */
} CPC_M16C_CAN_ERROR_T;
/* structure for CAN error conditions */
#define CPC_CAN_ECODE_ERRFRAME 0x01
typedef struct CPC_CAN_ERROR {
u8 ecode;
struct {
u8 cc_type; /* CAN controller type */
union {
CPC_SJA1000_CAN_ERROR_T sja1000;
CPC_M16C_CAN_ERROR_T m16c;
} regs;
} cc;
} CPC_CAN_ERROR_T;
/*
* Structure containing RX/TX error counter.
* This structure is used to request the
* values of the CAN controllers TX and RX
* error counter.
*/
typedef struct CPC_CAN_ERR_COUNTER {
u8 rx;
u8 tx;
} CPC_CAN_ERR_COUNTER_T;
/* If this flag is set, transmissions from PC to CPC are protected against loss */
#define CPC_SECURE_TO_CPC 0x01
/* If this flag is set, transmissions from CPC to PC are protected against loss */
#define CPC_SECURE_TO_PC 0x02
/* If this flag is set, the CAN-transmit buffer is checked to be free before sending a message */
#define CPC_SECURE_SEND 0x04
/*
* If this flag is set, the transmission complete flag is checked
* after sending a message
* THIS IS CURRENTLY ONLY IMPLEMENTED IN THE PASSIVE INTERFACE DRIVERS
*/
#define CPC_SECURE_TRANSMIT 0x08
/* main message type used between library and application */
typedef struct CPC_MSG {
u8 type; /* type of message */
u8 length; /* length of data within union 'msg' */
u8 msgid; /* confirmation handle */
u32 ts_sec; /* timestamp in seconds */
u32 ts_nsec; /* timestamp in nano seconds */
union {
u8 generic[CPC_MSG_LEN];
CPC_CAN_MSG_T canmsg;
CPC_CAN_PARAMS_T canparams;
CPC_CONFIRM_T confirmation;
CPC_INFO_T info;
CPC_OVERRUN_T overrun;
CPC_CAN_ERROR_T error;
CPC_CAN_ERR_COUNTER_T err_counter;
u8 busload;
u8 canstate;
} msg;
} CPC_MSG_T;
#endif /* CPC_HEADER */

View file

@ -1,83 +0,0 @@
/*
* CPCLIB
*
* Copyright (C) 2000-2008 EMS Dr. Thomas Wuensche
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#ifndef CPC_INT_H
#define CPC_INT_H
#include <linux/wait.h>
#define CPC_MSG_BUF_CNT 1500
#define CPC_PROC_DIR "driver/"
#undef dbg
#undef err
#undef info
/* Use our own dbg macro */
#define dbg(format, arg...) do { if (debug) printk( KERN_INFO format "\n" , ## arg); } while (0)
#define err(format, arg...) do { printk( KERN_INFO "ERROR " format "\n" , ## arg); } while (0)
#define info(format, arg...) do { printk( KERN_INFO format "\n" , ## arg); } while (0)
/* Macros help using of our buffers */
#define IsBufferFull(x) (!(x)->WnR) && ((x)->iidx == (x)->oidx)
#define IsBufferEmpty(x) ((x)->WnR) && ((x)->iidx == (x)->oidx)
#define IsBufferNotEmpty(x) (!(x)->WnR) || ((x)->iidx != (x)->oidx)
#define ResetBuffer(x) do { (x)->oidx = (x)->iidx=0; (x)->WnR = 1; } while(0);
#define CPC_BufWriteAllowed ((chan->oidx != chan->iidx) || chan->WnR)
typedef void (*chan_write_byte_t) (void *chan, unsigned int reg,
unsigned char val);
typedef unsigned char (*chan_read_byte_t) (void *chan, unsigned int reg);
typedef struct CPC_CHAN {
void __iomem * canBase; /* base address of SJA1000 */
chan_read_byte_t read_byte; /* CAN controller read access routine */
chan_write_byte_t write_byte; /* CAN controller write access routine */
CPC_MSG_T *buf; /* buffer for CPC msg */
unsigned int iidx;
unsigned int oidx;
unsigned int WnR;
unsigned int minor;
unsigned int locked;
unsigned int irqDisabled;
unsigned char cpcCtrlCANMessage;
unsigned char cpcCtrlCANState;
unsigned char cpcCtrlBUSState;
unsigned char controllerType;
unsigned long ovrTimeSec;
unsigned long ovrTimeNSec;
unsigned long ovrLockedBuffer;
CPC_OVERRUN_T ovr;
/* for debugging only */
unsigned int handledIrqs;
unsigned int lostMessages;
unsigned int sentStdCan;
unsigned int sentExtCan;
unsigned int sentStdRtr;
unsigned int sentExtRtr;
unsigned int recvStdCan;
unsigned int recvExtCan;
unsigned int recvStdRtr;
unsigned int recvExtRtr;
wait_queue_head_t *CPCWait_q;
void *private;
} CPC_CHAN_T;
#endif

View file

@ -1,86 +0,0 @@
/* Header for CPC-USB Driver ********************
* Copyright 1999, 2000, 2001
*
* Company: EMS Dr. Thomas Wuensche
* Sonnenhang 3
* 85304 Ilmmuenster
* Phone: +49-8441-490260
* Fax: +49-8441-81860
* email: support@ems-wuensche.com
* WWW: www.ems-wuensche.com
*/
#ifndef CPCUSB_H
#define CPCUSB_H
#undef err
#undef dbg
#undef info
/* Use our own dbg macro */
#define dbg(format, arg...) do { if (debug) printk(KERN_INFO "CPC-USB: " format "\n" , ## arg); } while (0)
#define info(format, arg...) do { printk(KERN_INFO "CPC-USB: " format "\n" , ## arg); } while (0)
#define err(format, arg...) do { printk(KERN_INFO "CPC-USB(ERROR): " format "\n" , ## arg); } while (0)
#define CPC_USB_CARD_CNT 4
typedef struct CPC_USB_READ_URB {
unsigned char *buffer; /* the buffer to send data */
size_t size; /* the size of the send buffer */
struct urb *urb; /* the urb used to send data */
} CPC_USB_READ_URB_T;
typedef struct CPC_USB_WRITE_URB {
unsigned char *buffer; /* the buffer to send data */
size_t size; /* the size of the send buffer */
struct urb *urb; /* the urb used to send data */
atomic_t busy; /* true if write urb is busy */
struct completion finished; /* wait for the write to finish */
} CPC_USB_WRITE_URB_T;
#define CPC_USB_URB_CNT 10
typedef struct CPC_USB {
struct usb_device *udev; /* save off the usb device pointer */
struct usb_interface *interface; /* the interface for this device */
unsigned char minor; /* the starting minor number for this device */
unsigned char num_ports; /* the number of ports this device has */
int num_intr_in; /* number of interrupt in endpoints we have */
int num_bulk_in; /* number of bulk in endpoints we have */
int num_bulk_out; /* number of bulk out endpoints we have */
CPC_USB_READ_URB_T urbs[CPC_USB_URB_CNT];
unsigned char intr_in_buffer[4]; /* interrupt transfer buffer */
struct urb *intr_in_urb; /* interrupt transfer urb */
CPC_USB_WRITE_URB_T wrUrbs[CPC_USB_URB_CNT];
int open; /* if the port is open or not */
int present; /* if the device is not disconnected */
struct semaphore sem; /* locks this structure */
int free_slots; /* free send slots of CPC-USB */
int idx;
spinlock_t slock;
char serialNumber[128]; /* serial number */
int productId; /* product id to differ between M16C and LPC2119 */
CPC_CHAN_T *chan;
} CPC_USB_T;
#define CPCTable CPCUSB_Table
#define CPC_DRIVER_VERSION "0.724"
#define CPC_DRIVER_SERIAL "not applicable"
#define OBUF_SIZE 255 /* 4096 */
/* read timeouts -- RD_NAK_TIMEOUT * RD_EXPIRE = Number of seconds */
#define RD_NAK_TIMEOUT (10*HZ) /* Default number of X seconds to wait */
#define RD_EXPIRE 12 /* Number of attempts to wait X seconds */
#define CPC_USB_BASE_MNR 0 /* CPC-USB start at minor 0 */
#endif

View file

@ -1,41 +0,0 @@
#ifndef _SJA2M16C_H
#define _SJA2M16C_H
#include "cpc.h"
#define BAUDRATE_TOLERANCE_PERCENT 1
#define SAMPLEPOINT_TOLERANCE_PERCENT 5
#define SAMPLEPOINT_UPPER_LIMIT 88
/* M16C parameters */
struct FIELD_C0CONR {
unsigned int brp:4;
unsigned int sam:1;
unsigned int pr:3;
unsigned int dummy:8;
};
struct FIELD_C1CONR {
unsigned int ph1:3;
unsigned int ph2:3;
unsigned int sjw:2;
unsigned int dummy:8;
};
typedef union C0CONR {
unsigned char c0con;
struct FIELD_C0CONR bc0con;
} C0CONR_T;
typedef union C1CONR {
unsigned char c1con;
struct FIELD_C1CONR bc1con;
} C1CONR_T;
#define SJA_TSEG1 ((pParams->btr1 & 0x0f)+1)
#define SJA_TSEG2 (((pParams->btr1 & 0x70)>>4)+1)
#define SJA_BRP ((pParams->btr0 & 0x3f)+1)
#define SJA_SJW ((pParams->btr0 & 0xc0)>>6)
#define SJA_SAM ((pParams->btr1 & 0x80)>>7)
int baudrate_m16c(int clk, int brp, int pr, int ph1, int ph2);
int samplepoint_m16c(int brp, int pr, int ph1, int ph2);
int SJA1000_TO_M16C_BASIC_Params(CPC_MSG_T *pMsg);
#endif

View file

@ -1,452 +0,0 @@
/****************************************************************************
*
* Copyright (c) 2003,2004 by EMS Dr. Thomas Wuensche
*
* - All rights reserved -
*
* This code is provided "as is" without warranty of any kind, either
* expressed or implied, including but not limited to the liability
* concerning the freedom from material defects, the fitness for parti-
* cular purposes or the freedom of proprietary rights of third parties.
*
*****************************************************************************
* Module name.: cpcusb
*****************************************************************************
* Include file: cpc.h
*****************************************************************************
* Project.....: Windows Driver Development Kit
* Filename....: sja2m16c.cpp
* Authors.....: (GU) Gerhard Uttenthaler
* (CS) Christian Schoett
*****************************************************************************
* Short descr.: converts baudrate between SJA1000 and M16C
*****************************************************************************
* Description.: handles the baudrate conversion from SJA1000 parameters to
* M16C parameters
*****************************************************************************
* Address : EMS Dr. Thomas Wuensche
* Sonnenhang 3
* D-85304 Ilmmuenster
* Tel. : +49-8441-490260
* Fax. : +49-8441-81860
* email: support@ems-wuensche.com
*****************************************************************************
* History
*****************************************************************************
* Version Date Auth Remark
*
* 01.00 ?? GU - initial release
* 01.10 ?????????? CS - adapted to fit into the USB Windows driver
* 02.00 18.08.2004 GU - improved the baudrate calculating algorithm
* - implemented acceptance filtering
* 02.10 10.09.2004 CS - adapted to fit into the USB Windows driver
*****************************************************************************
* ToDo's
*****************************************************************************
*/
/****************************************************************************/
/* I N C L U D E S
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/smp_lock.h>
#include <linux/completion.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
#include "cpc.h"
#include "cpc_int.h"
#include "cpcusb.h"
#include "sja2m16c.h"
/*********************************************************************/
int baudrate_m16c(int clk, int brp, int pr, int ph1, int ph2)
{
return (16000000 / (1 << clk)) / 2 / (brp + 1) / (1 + pr + 1 +
ph1 + 1 + ph2 +
1);
}
/*********************************************************************/
int samplepoint_m16c(int brp, int pr, int ph1, int ph2)
{
return (100 * (1 + pr + 1 + ph1 + 1)) / (1 + pr + 1 + ph1 + 1 +
ph2 + 1);
}
/****************************************************************************
* Function.....: SJA1000_TO_M16C_BASIC_Params
*
* Task.........: This routine converts SJA1000 CAN btr parameters into M16C
* parameters based on the sample point and the error. In
* addition it converts the acceptance filter parameters to
* suit the M16C parameters
*
* Parameters...: None
*
* Return values: None
*
* Comments.....:
*****************************************************************************
* History
*****************************************************************************
* 19.01.2005 CS - modifed the conversion of SJA1000 filter params into
* M16C params. Due to compatibility reasons with the
* older 82C200 CAN controller the SJA1000
****************************************************************************/
int SJA1000_TO_M16C_BASIC_Params(CPC_MSG_T * in)
{
int sjaBaudrate;
int sjaSamplepoint;
int *baudrate_error; // BRP[0..15], PR[0..7], PH1[0..7], PH2[0..7]
int *samplepoint_error; // BRP[0..15], PR[0..7], PH1[0..7], PH2[0..7]
int baudrate_error_merk;
int clk, brp, pr, ph1, ph2;
int clk_merk, brp_merk, pr_merk, ph1_merk, ph2_merk;
int index;
unsigned char acc_code0, acc_code1, acc_code2, acc_code3;
unsigned char acc_mask0, acc_mask1, acc_mask2, acc_mask3;
CPC_MSG_T * out;
C0CONR_T c0con;
C1CONR_T c1con;
int tmpAccCode;
int tmpAccMask;
// we have to convert the parameters into M16C parameters
CPC_SJA1000_PARAMS_T * pParams;
// check if the type is CAN parameters and if we have to convert the given params
if (in->type != CPC_CMD_T_CAN_PRMS
|| in->msg.canparams.cc_type != SJA1000)
return 0;
pParams =
(CPC_SJA1000_PARAMS_T *) & in->msg.canparams.cc_params.sja1000;
acc_code0 = pParams->acc_code0;
acc_code1 = pParams->acc_code1;
acc_code2 = pParams->acc_code2;
acc_code3 = pParams->acc_code3;
acc_mask0 = pParams->acc_mask0;
acc_mask1 = pParams->acc_mask1;
acc_mask2 = pParams->acc_mask2;
acc_mask3 = pParams->acc_mask3;
#ifdef _DEBUG_OUTPUT_CAN_PARAMS
info("acc_code0: %2.2Xh\n", acc_code0);
info("acc_code1: %2.2Xh\n", acc_code1);
info("acc_code2: %2.2Xh\n", acc_code2);
info("acc_code3: %2.2Xh\n", acc_code3);
info("acc_mask0: %2.2Xh\n", acc_mask0);
info("acc_mask1: %2.2Xh\n", acc_mask1);
info("acc_mask2: %2.2Xh\n", acc_mask2);
info("acc_mask3: %2.2Xh\n", acc_mask3);
#endif /* */
if (!
(baudrate_error =
(int *) vmalloc(sizeof(int) * 16 * 8 * 8 * 8 * 5))) {
err("Could not allocate memory\n");
return -3;
}
if (!
(samplepoint_error =
(int *) vmalloc(sizeof(int) * 16 * 8 * 8 * 8 * 5))) {
err("Could not allocate memory\n");
vfree(baudrate_error);
return -3;
}
memset(baudrate_error, 0xff, sizeof(baudrate_error));
memset(samplepoint_error, 0xff, sizeof(baudrate_error));
sjaBaudrate =
16000000 / 2 / SJA_BRP / (1 + SJA_TSEG1 + SJA_TSEG2);
sjaSamplepoint =
100 * (1 + SJA_TSEG1) / (1 + SJA_TSEG1 + SJA_TSEG2);
if (sjaBaudrate == 0) {
vfree(baudrate_error);
vfree(samplepoint_error);
return -2;
}
#ifdef _DEBUG_OUTPUT_CAN_PARAMS
info("\nStarting SJA CAN params\n");
info("-------------------------\n");
info("TS1 : %2.2Xh TS2 : %2.2Xh\n", SJA_TSEG1, SJA_TSEG2);
info("BTR0 : %2.2Xh BTR1: %2.2Xh\n", pParams->btr0,
pParams->btr1);
info("Baudrate: %d.%dkBaud\n", sjaBaudrate / 1000,
sjaBaudrate % 1000);
info("Sample P: 0.%d\n", sjaSamplepoint);
info("\n");
#endif /* */
c0con.bc0con.sam = SJA_SAM;
c1con.bc1con.sjw = SJA_SJW;
// calculate errors for all baudrates
index = 0;
for (clk = 0; clk < 5; clk++) {
for (brp = 0; brp < 16; brp++) {
for (pr = 0; pr < 8; pr++) {
for (ph1 = 0; ph1 < 8; ph1++) {
for (ph2 = 0; ph2 < 8; ph2++) {
baudrate_error[index] =
100 *
abs(baudrate_m16c
(clk, brp, pr, ph1,
ph2) -
sjaBaudrate) /
sjaBaudrate;
samplepoint_error[index] =
abs(samplepoint_m16c
(brp, pr, ph1,
ph2) -
sjaSamplepoint);
#if 0
info
("Baudrate : %d kBaud\n",
baudrate_m16c(clk,
brp, pr,
ph1,
ph2));
info
("Baudrate Error: %d\n",
baudrate_error
[index]);
info
("Sample P Error: %d\n",
samplepoint_error
[index]);
info
("clk : %d\n",
clk);
#endif /* */
index++;
}
}
}
}
}
// mark all baudrate_error entries which are outer limits
index = 0;
for (clk = 0; clk < 5; clk++) {
for (brp = 0; brp < 16; brp++) {
for (pr = 0; pr < 8; pr++) {
for (ph1 = 0; ph1 < 8; ph1++) {
for (ph2 = 0; ph2 < 8; ph2++) {
if ((baudrate_error[index]
>
BAUDRATE_TOLERANCE_PERCENT)
||
(samplepoint_error
[index] >
SAMPLEPOINT_TOLERANCE_PERCENT)
||
(samplepoint_m16c
(brp, pr, ph1,
ph2) >
SAMPLEPOINT_UPPER_LIMIT))
{
baudrate_error
[index] = -1;
} else
if (((1 + pr + 1 +
ph1 + 1 + ph2 +
1) < 8)
||
((1 + pr + 1 +
ph1 + 1 + ph2 +
1) > 25)) {
baudrate_error
[index] = -1;
}
#if 0
else {
info
("Baudrate : %d kBaud\n",
baudrate_m16c
(clk, brp, pr,
ph1, ph2));
info
("Baudrate Error: %d\n",
baudrate_error
[index]);
info
("Sample P Error: %d\n",
samplepoint_error
[index]);
}
#endif /* */
index++;
}
}
}
}
}
// find list of minimum of baudrate_error within unmarked entries
clk_merk = brp_merk = pr_merk = ph1_merk = ph2_merk = 0;
baudrate_error_merk = 100;
index = 0;
for (clk = 0; clk < 5; clk++) {
for (brp = 0; brp < 16; brp++) {
for (pr = 0; pr < 8; pr++) {
for (ph1 = 0; ph1 < 8; ph1++) {
for (ph2 = 0; ph2 < 8; ph2++) {
if (baudrate_error[index]
!= -1) {
if (baudrate_error
[index] <
baudrate_error_merk)
{
baudrate_error_merk
=
baudrate_error
[index];
brp_merk =
brp;
pr_merk =
pr;
ph1_merk =
ph1;
ph2_merk =
ph2;
clk_merk =
clk;
#if 0
info
("brp: %2.2Xh pr: %2.2Xh ph1: %2.2Xh ph2: %2.2Xh\n",
brp,
pr,
ph1,
ph2);
info
("Baudrate : %d kBaud\n",
baudrate_m16c
(clk,
brp,
pr,
ph1,
ph2));
info
("Baudrate Error: %d\n",
baudrate_error
[index]);
info
("Sample P Error: %d\n",
samplepoint_error
[index]);
#endif /* */
}
}
index++;
}
}
}
}
}
if (baudrate_error_merk == 100) {
info("ERROR: Could not convert CAN init parameter\n");
vfree(baudrate_error);
vfree(samplepoint_error);
return -1;
}
// setting m16c CAN parameter
c0con.bc0con.brp = brp_merk;
c0con.bc0con.pr = pr_merk;
c1con.bc1con.ph1 = ph1_merk;
c1con.bc1con.ph2 = ph2_merk;
#ifdef _DEBUG_OUTPUT_CAN_PARAMS
info("\nResulting M16C CAN params\n");
info("-------------------------\n");
info("clk : %2.2Xh\n", clk_merk);
info("ph1 : %2.2Xh ph2: %2.2Xh\n", c1con.bc1con.ph1 + 1,
c1con.bc1con.ph2 + 1);
info("pr : %2.2Xh brp: %2.2Xh\n", c0con.bc0con.pr + 1,
c0con.bc0con.brp + 1);
info("sjw : %2.2Xh sam: %2.2Xh\n", c1con.bc1con.sjw,
c0con.bc0con.sam);
info("co1 : %2.2Xh co0: %2.2Xh\n", c1con.c1con, c0con.c0con);
info("Baudrate: %d.%dBaud\n",
baudrate_m16c(clk_merk, c0con.bc0con.brp, c0con.bc0con.pr,
c1con.bc1con.ph1, c1con.bc1con.ph2) / 1000,
baudrate_m16c(clk_merk, c0con.bc0con.brp, c0con.bc0con.pr,
c1con.bc1con.ph1, c1con.bc1con.ph2) % 1000);
info("Sample P: 0.%d\n",
samplepoint_m16c(c0con.bc0con.brp, c0con.bc0con.pr,
c1con.bc1con.ph1, c1con.bc1con.ph2));
info("\n");
#endif /* */
out = in;
out->type = 6;
out->length = sizeof(CPC_M16C_BASIC_PARAMS_T) + 1;
out->msg.canparams.cc_type = M16C_BASIC;
out->msg.canparams.cc_params.m16c_basic.con0 = c0con.c0con;
out->msg.canparams.cc_params.m16c_basic.con1 = c1con.c1con;
out->msg.canparams.cc_params.m16c_basic.ctlr0 = 0x4C;
out->msg.canparams.cc_params.m16c_basic.ctlr1 = 0x00;
out->msg.canparams.cc_params.m16c_basic.clk = clk_merk;
out->msg.canparams.cc_params.m16c_basic.acc_std_code0 =
acc_code0;
out->msg.canparams.cc_params.m16c_basic.acc_std_code1 = acc_code1;
// info("code0: 0x%2.2X, code1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_code0, out->msg.canparams.cc_params.m16c_basic.acc_std_code1);
tmpAccCode = (acc_code1 >> 5) + (acc_code0 << 3);
out->msg.canparams.cc_params.m16c_basic.acc_std_code0 =
(unsigned char) tmpAccCode;
out->msg.canparams.cc_params.m16c_basic.acc_std_code1 =
(unsigned char) (tmpAccCode >> 8);
// info("code0: 0x%2.2X, code1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_code0, out->msg.canparams.cc_params.m16c_basic.acc_std_code1);
out->msg.canparams.cc_params.m16c_basic.acc_std_mask0 =
~acc_mask0;
out->msg.canparams.cc_params.m16c_basic.acc_std_mask1 =
~acc_mask1;
// info("mask0: 0x%2.2X, mask1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_mask0, out->msg.canparams.cc_params.m16c_basic.acc_std_mask1);
tmpAccMask = ((acc_mask1) >> 5) + ((acc_mask0) << 3);
// info("tmpAccMask: 0x%4.4X\n", tmpAccMask);
out->msg.canparams.cc_params.m16c_basic.acc_std_mask0 =
(unsigned char) ~tmpAccMask;
out->msg.canparams.cc_params.m16c_basic.acc_std_mask1 =
(unsigned char) ~(tmpAccMask >> 8);
// info("mask0: 0x%2.2X, mask1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_mask0, out->msg.canparams.cc_params.m16c_basic.acc_std_mask1);
out->msg.canparams.cc_params.m16c_basic.acc_ext_code0 =
(unsigned char) tmpAccCode;
out->msg.canparams.cc_params.m16c_basic.acc_ext_code1 =
(unsigned char) (tmpAccCode >> 8);
out->msg.canparams.cc_params.m16c_basic.acc_ext_code2 = acc_code2;
out->msg.canparams.cc_params.m16c_basic.acc_ext_code3 = acc_code3;
out->msg.canparams.cc_params.m16c_basic.acc_ext_mask0 =
(unsigned char) ~tmpAccMask;
out->msg.canparams.cc_params.m16c_basic.acc_ext_mask1 =
(unsigned char) ~(tmpAccMask >> 8);
out->msg.canparams.cc_params.m16c_basic.acc_ext_mask2 =
~acc_mask2;
out->msg.canparams.cc_params.m16c_basic.acc_ext_mask3 =
~acc_mask3;
vfree(baudrate_error);
vfree(samplepoint_error);
return 0;
}

View file

@ -187,6 +187,7 @@ extern struct sock *netlink_kernel_create(struct net *net,
extern void netlink_kernel_release(struct sock *sk); extern void netlink_kernel_release(struct sock *sk);
extern int __netlink_change_ngroups(struct sock *sk, unsigned int groups); extern int __netlink_change_ngroups(struct sock *sk, unsigned int groups);
extern int netlink_change_ngroups(struct sock *sk, unsigned int groups); extern int netlink_change_ngroups(struct sock *sk, unsigned int groups);
extern void __netlink_clear_multicast_users(struct sock *sk, unsigned int group);
extern void netlink_clear_multicast_users(struct sock *sk, unsigned int group); extern void netlink_clear_multicast_users(struct sock *sk, unsigned int group);
extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err); extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err);
extern int netlink_has_listeners(struct sock *sk, unsigned int group); extern int netlink_has_listeners(struct sock *sk, unsigned int group);

View file

@ -38,6 +38,7 @@
#define PNPIPE_IFINDEX 2 #define PNPIPE_IFINDEX 2
#define PNADDR_ANY 0 #define PNADDR_ANY 0
#define PNADDR_BROADCAST 0xFC
#define PNPORT_RESOURCE_ROUTING 0 #define PNPORT_RESOURCE_ROUTING 0
/* Values for PNPIPE_ENCAP option */ /* Values for PNPIPE_ENCAP option */

View file

@ -89,6 +89,7 @@ struct driver_info {
#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */ #define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
#define FLAG_WLAN 0x0080 /* use "wlan%d" names */ #define FLAG_WLAN 0x0080 /* use "wlan%d" names */
#define FLAG_AVOID_UNLINK_URBS 0x0100 /* don't unlink urbs at usbnet_stop() */ #define FLAG_AVOID_UNLINK_URBS 0x0100 /* don't unlink urbs at usbnet_stop() */
#define FLAG_SEND_ZLP 0x0200 /* hw requires ZLPs are sent */
/* init device ... can sleep, or cause probe() failure */ /* init device ... can sleep, or cause probe() failure */

View file

@ -12,7 +12,6 @@ struct ip_tunnel
struct ip_tunnel *next; struct ip_tunnel *next;
struct net_device *dev; struct net_device *dev;
int recursion; /* Depth of hard_start_xmit recursion */
int err_count; /* Number of arrived ICMP errors */ int err_count; /* Number of arrived ICMP errors */
unsigned long err_time; /* Time when the last ICMP error arrived */ unsigned long err_time; /* Time when the last ICMP error arrived */

View file

@ -49,6 +49,7 @@ cond_syscall(sys_sendmsg);
cond_syscall(compat_sys_sendmsg); cond_syscall(compat_sys_sendmsg);
cond_syscall(sys_recvmsg); cond_syscall(sys_recvmsg);
cond_syscall(compat_sys_recvmsg); cond_syscall(compat_sys_recvmsg);
cond_syscall(compat_sys_recvfrom);
cond_syscall(sys_socketcall); cond_syscall(sys_socketcall);
cond_syscall(sys_futex); cond_syscall(sys_futex);
cond_syscall(compat_sys_futex); cond_syscall(compat_sys_futex);

View file

@ -671,7 +671,7 @@ static char *ip4_string(char *p, const u8 *addr, bool leading_zeros)
return p; return p;
} }
static char *ip6_compressed_string(char *p, const struct in6_addr *addr) static char *ip6_compressed_string(char *p, const char *addr)
{ {
int i; int i;
int j; int j;
@ -683,7 +683,12 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr)
u8 hi; u8 hi;
u8 lo; u8 lo;
bool needcolon = false; bool needcolon = false;
bool useIPv4 = ipv6_addr_v4mapped(addr) || ipv6_addr_is_isatap(addr); bool useIPv4;
struct in6_addr in6;
memcpy(&in6, addr, sizeof(struct in6_addr));
useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6);
memset(zerolength, 0, sizeof(zerolength)); memset(zerolength, 0, sizeof(zerolength));
@ -695,7 +700,7 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr)
/* find position of longest 0 run */ /* find position of longest 0 run */
for (i = 0; i < range; i++) { for (i = 0; i < range; i++) {
for (j = i; j < range; j++) { for (j = i; j < range; j++) {
if (addr->s6_addr16[j] != 0) if (in6.s6_addr16[j] != 0)
break; break;
zerolength[i]++; zerolength[i]++;
} }
@ -722,7 +727,7 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr)
needcolon = false; needcolon = false;
} }
/* hex u16 without leading 0s */ /* hex u16 without leading 0s */
word = ntohs(addr->s6_addr16[i]); word = ntohs(in6.s6_addr16[i]);
hi = word >> 8; hi = word >> 8;
lo = word & 0xff; lo = word & 0xff;
if (hi) { if (hi) {
@ -741,19 +746,19 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr)
if (useIPv4) { if (useIPv4) {
if (needcolon) if (needcolon)
*p++ = ':'; *p++ = ':';
p = ip4_string(p, &addr->s6_addr[12], false); p = ip4_string(p, &in6.s6_addr[12], false);
} }
*p = '\0'; *p = '\0';
return p; return p;
} }
static char *ip6_string(char *p, const struct in6_addr *addr, const char *fmt) static char *ip6_string(char *p, const char *addr, const char *fmt)
{ {
int i; int i;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
p = pack_hex_byte(p, addr->s6_addr[2 * i]); p = pack_hex_byte(p, *addr++);
p = pack_hex_byte(p, addr->s6_addr[2 * i + 1]); p = pack_hex_byte(p, *addr++);
if (fmt[0] == 'I' && i != 7) if (fmt[0] == 'I' && i != 7)
*p++ = ':'; *p++ = ':';
} }
@ -768,9 +773,9 @@ static char *ip6_addr_string(char *buf, char *end, const u8 *addr,
char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")]; char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
if (fmt[0] == 'I' && fmt[2] == 'c') if (fmt[0] == 'I' && fmt[2] == 'c')
ip6_compressed_string(ip6_addr, (const struct in6_addr *)addr); ip6_compressed_string(ip6_addr, addr);
else else
ip6_string(ip6_addr, (const struct in6_addr *)addr, fmt); ip6_string(ip6_addr, addr, fmt);
return string(buf, end, ip6_addr, spec); return string(buf, end, ip6_addr, spec);
} }

View file

@ -1781,8 +1781,8 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
ax25_info.idletimer = ax25_display_timer(&ax25->idletimer) / (60 * HZ); ax25_info.idletimer = ax25_display_timer(&ax25->idletimer) / (60 * HZ);
ax25_info.n2count = ax25->n2count; ax25_info.n2count = ax25->n2count;
ax25_info.state = ax25->state; ax25_info.state = ax25->state;
ax25_info.rcv_q = sk_wmem_alloc_get(sk); ax25_info.rcv_q = sk_rmem_alloc_get(sk);
ax25_info.snd_q = sk_rmem_alloc_get(sk); ax25_info.snd_q = sk_wmem_alloc_get(sk);
ax25_info.vs = ax25->vs; ax25_info.vs = ax25->vs;
ax25_info.vr = ax25->vr; ax25_info.vr = ax25->vr;
ax25_info.va = ax25->va; ax25_info.va = ax25->va;

View file

@ -192,11 +192,10 @@
#define F_QUEUE_MAP_CPU (1<<14) /* queue map mirrors smp_processor_id() */ #define F_QUEUE_MAP_CPU (1<<14) /* queue map mirrors smp_processor_id() */
/* Thread control flag bits */ /* Thread control flag bits */
#define T_TERMINATE (1<<0) #define T_STOP (1<<0) /* Stop run */
#define T_STOP (1<<1) /* Stop run */ #define T_RUN (1<<1) /* Start run */
#define T_RUN (1<<2) /* Start run */ #define T_REMDEVALL (1<<2) /* Remove all devs */
#define T_REMDEVALL (1<<3) /* Remove all devs */ #define T_REMDEV (1<<3) /* Remove one dev */
#define T_REMDEV (1<<4) /* Remove one dev */
/* If lock -- can be removed after some work */ /* If lock -- can be removed after some work */
#define if_lock(t) spin_lock(&(t->if_lock)); #define if_lock(t) spin_lock(&(t->if_lock));
@ -2105,7 +2104,7 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until) static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
{ {
ktime_t start; ktime_t start_time, end_time;
s32 remaining; s32 remaining;
struct hrtimer_sleeper t; struct hrtimer_sleeper t;
@ -2116,7 +2115,7 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
if (remaining <= 0) if (remaining <= 0)
return; return;
start = ktime_now(); start_time = ktime_now();
if (remaining < 100) if (remaining < 100)
udelay(remaining); /* really small just spin */ udelay(remaining); /* really small just spin */
else { else {
@ -2135,7 +2134,10 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
} while (t.task && pkt_dev->running && !signal_pending(current)); } while (t.task && pkt_dev->running && !signal_pending(current));
__set_current_state(TASK_RUNNING); __set_current_state(TASK_RUNNING);
} }
pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), start)); end_time = ktime_now();
pkt_dev->idle_acc += ktime_to_ns(ktime_sub(end_time, start_time));
pkt_dev->next_tx = ktime_add_ns(end_time, pkt_dev->delay);
} }
static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev) static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev)
@ -3365,18 +3367,28 @@ static void pktgen_rem_thread(struct pktgen_thread *t)
mutex_unlock(&pktgen_thread_lock); mutex_unlock(&pktgen_thread_lock);
} }
static void idle(struct pktgen_dev *pkt_dev) static void pktgen_resched(struct pktgen_dev *pkt_dev)
{ {
ktime_t idle_start = ktime_now(); ktime_t idle_start = ktime_now();
schedule();
if (need_resched())
schedule();
else
cpu_relax();
pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), idle_start)); pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), idle_start));
} }
static void pktgen_wait_for_skb(struct pktgen_dev *pkt_dev)
{
ktime_t idle_start = ktime_now();
while (atomic_read(&(pkt_dev->skb->users)) != 1) {
if (signal_pending(current))
break;
if (need_resched())
pktgen_resched(pkt_dev);
else
cpu_relax();
}
pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), idle_start));
}
static void pktgen_xmit(struct pktgen_dev *pkt_dev) static void pktgen_xmit(struct pktgen_dev *pkt_dev)
{ {
@ -3387,36 +3399,21 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
u16 queue_map; u16 queue_map;
int ret; int ret;
if (pkt_dev->delay) { /* If device is offline, then don't send */
spin(pkt_dev, pkt_dev->next_tx); if (unlikely(!netif_running(odev) || !netif_carrier_ok(odev))) {
pktgen_stop_device(pkt_dev);
/* This is max DELAY, this has special meaning of
* "never transmit"
*/
if (pkt_dev->delay == ULLONG_MAX) {
pkt_dev->next_tx = ktime_add_ns(ktime_now(), ULONG_MAX);
return;
}
}
if (!pkt_dev->skb) {
set_cur_queue_map(pkt_dev);
queue_map = pkt_dev->cur_queue_map;
} else {
queue_map = skb_get_queue_mapping(pkt_dev->skb);
}
txq = netdev_get_tx_queue(odev, queue_map);
/* Did we saturate the queue already? */
if (netif_tx_queue_stopped(txq) || netif_tx_queue_frozen(txq)) {
/* If device is down, then all queues are permnantly frozen */
if (netif_running(odev))
idle(pkt_dev);
else
pktgen_stop_device(pkt_dev);
return; return;
} }
/* This is max DELAY, this has special meaning of
* "never transmit"
*/
if (unlikely(pkt_dev->delay == ULLONG_MAX)) {
pkt_dev->next_tx = ktime_add_ns(ktime_now(), ULONG_MAX);
return;
}
/* If no skb or clone count exhausted then get new one */
if (!pkt_dev->skb || (pkt_dev->last_ok && if (!pkt_dev->skb || (pkt_dev->last_ok &&
++pkt_dev->clone_count >= pkt_dev->clone_skb)) { ++pkt_dev->clone_count >= pkt_dev->clone_skb)) {
/* build a new pkt */ /* build a new pkt */
@ -3435,54 +3432,45 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
pkt_dev->clone_count = 0; /* reset counter */ pkt_dev->clone_count = 0; /* reset counter */
} }
/* fill_packet() might have changed the queue */ if (pkt_dev->delay && pkt_dev->last_ok)
spin(pkt_dev, pkt_dev->next_tx);
queue_map = skb_get_queue_mapping(pkt_dev->skb); queue_map = skb_get_queue_mapping(pkt_dev->skb);
txq = netdev_get_tx_queue(odev, queue_map); txq = netdev_get_tx_queue(odev, queue_map);
__netif_tx_lock_bh(txq); __netif_tx_lock_bh(txq);
atomic_inc(&(pkt_dev->skb->users));
if (unlikely(netif_tx_queue_stopped(txq) || netif_tx_queue_frozen(txq))) if (unlikely(netif_tx_queue_stopped(txq) || netif_tx_queue_frozen(txq)))
pkt_dev->last_ok = 0; ret = NETDEV_TX_BUSY;
else { else
atomic_inc(&(pkt_dev->skb->users));
retry_now:
ret = (*xmit)(pkt_dev->skb, odev); ret = (*xmit)(pkt_dev->skb, odev);
switch (ret) {
case NETDEV_TX_OK:
txq_trans_update(txq);
pkt_dev->last_ok = 1;
pkt_dev->sofar++;
pkt_dev->seq_num++;
pkt_dev->tx_bytes += pkt_dev->cur_pkt_size;
break;
case NETDEV_TX_LOCKED:
cpu_relax();
goto retry_now;
default: /* Drivers are not supposed to return other values! */
if (net_ratelimit())
pr_info("pktgen: %s xmit error: %d\n",
odev->name, ret);
pkt_dev->errors++;
/* fallthru */
case NETDEV_TX_BUSY:
/* Retry it next time */
atomic_dec(&(pkt_dev->skb->users));
pkt_dev->last_ok = 0;
}
if (pkt_dev->delay) switch (ret) {
pkt_dev->next_tx = ktime_add_ns(ktime_now(), case NETDEV_TX_OK:
pkt_dev->delay); txq_trans_update(txq);
pkt_dev->last_ok = 1;
pkt_dev->sofar++;
pkt_dev->seq_num++;
pkt_dev->tx_bytes += pkt_dev->cur_pkt_size;
break;
default: /* Drivers are not supposed to return other values! */
if (net_ratelimit())
pr_info("pktgen: %s xmit error: %d\n",
odev->name, ret);
pkt_dev->errors++;
/* fallthru */
case NETDEV_TX_LOCKED:
case NETDEV_TX_BUSY:
/* Retry it next time */
atomic_dec(&(pkt_dev->skb->users));
pkt_dev->last_ok = 0;
} }
__netif_tx_unlock_bh(txq); __netif_tx_unlock_bh(txq);
/* If pkt_dev->count is zero, then run forever */ /* If pkt_dev->count is zero, then run forever */
if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) { if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) {
while (atomic_read(&(pkt_dev->skb->users)) != 1) { pktgen_wait_for_skb(pkt_dev);
if (signal_pending(current))
break;
idle(pkt_dev);
}
/* Done with this */ /* Done with this */
pktgen_stop_device(pkt_dev); pktgen_stop_device(pkt_dev);
@ -3515,20 +3503,24 @@ static int pktgen_thread_worker(void *arg)
while (!kthread_should_stop()) { while (!kthread_should_stop()) {
pkt_dev = next_to_run(t); pkt_dev = next_to_run(t);
if (!pkt_dev && if (unlikely(!pkt_dev && t->control == 0)) {
(t->control & (T_STOP | T_RUN | T_REMDEVALL | T_REMDEV)) wait_event_interruptible_timeout(t->queue,
== 0) { t->control != 0,
prepare_to_wait(&(t->queue), &wait, HZ/10);
TASK_INTERRUPTIBLE); continue;
schedule_timeout(HZ / 10);
finish_wait(&(t->queue), &wait);
} }
__set_current_state(TASK_RUNNING); __set_current_state(TASK_RUNNING);
if (pkt_dev) if (likely(pkt_dev)) {
pktgen_xmit(pkt_dev); pktgen_xmit(pkt_dev);
if (need_resched())
pktgen_resched(pkt_dev);
else
cpu_relax();
}
if (t->control & T_STOP) { if (t->control & T_STOP) {
pktgen_stop(t); pktgen_stop(t);
t->control &= ~(T_STOP); t->control &= ~(T_STOP);

View file

@ -66,10 +66,7 @@
solution, but it supposes maintaing new variable in ALL solution, but it supposes maintaing new variable in ALL
skb, even if no tunneling is used. skb, even if no tunneling is used.
Current solution: t->recursion lock breaks dead loops. It looks Current solution: HARD_TX_LOCK lock breaks dead loops.
like dev->tbusy flag, but I preferred new variable, because
the semantics is different. One day, when hard_start_xmit
will be multithreaded we will have to use skb->encapsulation.
@ -678,11 +675,6 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
__be32 dst; __be32 dst;
int mtu; int mtu;
if (tunnel->recursion++) {
stats->collisions++;
goto tx_error;
}
if (dev->type == ARPHRD_ETHER) if (dev->type == ARPHRD_ETHER)
IPCB(skb)->flags = 0; IPCB(skb)->flags = 0;
@ -820,7 +812,6 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
ip_rt_put(rt); ip_rt_put(rt);
stats->tx_dropped++; stats->tx_dropped++;
dev_kfree_skb(skb); dev_kfree_skb(skb);
tunnel->recursion--;
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
if (skb->sk) if (skb->sk)
@ -888,7 +879,6 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
nf_reset(skb); nf_reset(skb);
IPTUNNEL_XMIT(); IPTUNNEL_XMIT();
tunnel->recursion--;
return NETDEV_TX_OK; return NETDEV_TX_OK;
tx_error_icmp: tx_error_icmp:
@ -897,7 +887,6 @@ tx_error_icmp:
tx_error: tx_error:
stats->tx_errors++; stats->tx_errors++;
dev_kfree_skb(skb); dev_kfree_skb(skb);
tunnel->recursion--;
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }

View file

@ -611,6 +611,9 @@ static int do_ip_setsockopt(struct sock *sk, int level,
* Check the arguments are allowable * Check the arguments are allowable
*/ */
if (optlen < sizeof(struct in_addr))
goto e_inval;
err = -EFAULT; err = -EFAULT;
if (optlen >= sizeof(struct ip_mreqn)) { if (optlen >= sizeof(struct ip_mreqn)) {
if (copy_from_user(&mreq, optval, sizeof(mreq))) if (copy_from_user(&mreq, optval, sizeof(mreq)))

View file

@ -402,11 +402,6 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
__be32 dst = tiph->daddr; __be32 dst = tiph->daddr;
int mtu; int mtu;
if (tunnel->recursion++) {
stats->collisions++;
goto tx_error;
}
if (skb->protocol != htons(ETH_P_IP)) if (skb->protocol != htons(ETH_P_IP))
goto tx_error; goto tx_error;
@ -485,7 +480,6 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
ip_rt_put(rt); ip_rt_put(rt);
stats->tx_dropped++; stats->tx_dropped++;
dev_kfree_skb(skb); dev_kfree_skb(skb);
tunnel->recursion--;
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
if (skb->sk) if (skb->sk)
@ -523,7 +517,6 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
nf_reset(skb); nf_reset(skb);
IPTUNNEL_XMIT(); IPTUNNEL_XMIT();
tunnel->recursion--;
return NETDEV_TX_OK; return NETDEV_TX_OK;
tx_error_icmp: tx_error_icmp:
@ -531,7 +524,6 @@ tx_error_icmp:
tx_error: tx_error:
stats->tx_errors++; stats->tx_errors++;
dev_kfree_skb(skb); dev_kfree_skb(skb);
tunnel->recursion--;
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }

View file

@ -1043,11 +1043,6 @@ ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
struct net_device_stats *stats = &t->dev->stats; struct net_device_stats *stats = &t->dev->stats;
int ret; int ret;
if (t->recursion++) {
stats->collisions++;
goto tx_err;
}
switch (skb->protocol) { switch (skb->protocol) {
case htons(ETH_P_IP): case htons(ETH_P_IP):
ret = ip4ip6_tnl_xmit(skb, dev); ret = ip4ip6_tnl_xmit(skb, dev);
@ -1062,14 +1057,12 @@ ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
if (ret < 0) if (ret < 0)
goto tx_err; goto tx_err;
t->recursion--;
return NETDEV_TX_OK; return NETDEV_TX_OK;
tx_err: tx_err:
stats->tx_errors++; stats->tx_errors++;
stats->tx_dropped++; stats->tx_dropped++;
kfree_skb(skb); kfree_skb(skb);
t->recursion--;
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }

View file

@ -626,11 +626,6 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
struct in6_addr *addr6; struct in6_addr *addr6;
int addr_type; int addr_type;
if (tunnel->recursion++) {
stats->collisions++;
goto tx_error;
}
if (skb->protocol != htons(ETH_P_IPV6)) if (skb->protocol != htons(ETH_P_IPV6))
goto tx_error; goto tx_error;
@ -753,7 +748,6 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
ip_rt_put(rt); ip_rt_put(rt);
stats->tx_dropped++; stats->tx_dropped++;
dev_kfree_skb(skb); dev_kfree_skb(skb);
tunnel->recursion--;
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
if (skb->sk) if (skb->sk)
@ -794,7 +788,6 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
nf_reset(skb); nf_reset(skb);
IPTUNNEL_XMIT(); IPTUNNEL_XMIT();
tunnel->recursion--;
return NETDEV_TX_OK; return NETDEV_TX_OK;
tx_error_icmp: tx_error_icmp:
@ -802,7 +795,6 @@ tx_error_icmp:
tx_error: tx_error:
stats->tx_errors++; stats->tx_errors++;
dev_kfree_skb(skb); dev_kfree_skb(skb);
tunnel->recursion--;
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }

View file

@ -90,8 +90,8 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
bss->dtim_period = tim_ie->dtim_period; bss->dtim_period = tim_ie->dtim_period;
} }
/* set default value for buggy APs */ /* set default value for buggy AP/no TIM element */
if (!elems->tim || bss->dtim_period == 0) if (bss->dtim_period == 0)
bss->dtim_period = 1; bss->dtim_period = 1;
bss->supp_rates_len = 0; bss->supp_rates_len = 0;

View file

@ -1609,6 +1609,16 @@ int netlink_change_ngroups(struct sock *sk, unsigned int groups)
return err; return err;
} }
void __netlink_clear_multicast_users(struct sock *ksk, unsigned int group)
{
struct sock *sk;
struct hlist_node *node;
struct netlink_table *tbl = &nl_table[ksk->sk_protocol];
sk_for_each_bound(sk, node, &tbl->mc_list)
netlink_update_socket_mc(nlk_sk(sk), group, 0);
}
/** /**
* netlink_clear_multicast_users - kick off multicast listeners * netlink_clear_multicast_users - kick off multicast listeners
* *
@ -1619,15 +1629,8 @@ int netlink_change_ngroups(struct sock *sk, unsigned int groups)
*/ */
void netlink_clear_multicast_users(struct sock *ksk, unsigned int group) void netlink_clear_multicast_users(struct sock *ksk, unsigned int group)
{ {
struct sock *sk;
struct hlist_node *node;
struct netlink_table *tbl = &nl_table[ksk->sk_protocol];
netlink_table_grab(); netlink_table_grab();
__netlink_clear_multicast_users(ksk, group);
sk_for_each_bound(sk, node, &tbl->mc_list)
netlink_update_socket_mc(nlk_sk(sk), group, 0);
netlink_table_ungrab(); netlink_table_ungrab();
} }

View file

@ -220,10 +220,12 @@ static void __genl_unregister_mc_group(struct genl_family *family,
struct net *net; struct net *net;
BUG_ON(grp->family != family); BUG_ON(grp->family != family);
netlink_table_grab();
rcu_read_lock(); rcu_read_lock();
for_each_net_rcu(net) for_each_net_rcu(net)
netlink_clear_multicast_users(net->genl_sock, grp->id); __netlink_clear_multicast_users(net->genl_sock, grp->id);
rcu_read_unlock(); rcu_read_unlock();
netlink_table_ungrab();
clear_bit(grp->id, mc_groups); clear_bit(grp->id, mc_groups);
list_del(&grp->list); list_del(&grp->list);

View file

@ -168,6 +168,12 @@ static int pn_send(struct sk_buff *skb, struct net_device *dev,
goto drop; goto drop;
} }
/* Broadcast sending is not implemented */
if (pn_addr(dst) == PNADDR_BROADCAST) {
err = -EOPNOTSUPP;
goto drop;
}
skb_reset_transport_header(skb); skb_reset_transport_header(skb);
WARN_ON(skb_headroom(skb) & 1); /* HW assumes word alignment */ WARN_ON(skb_headroom(skb) & 1); /* HW assumes word alignment */
skb_push(skb, sizeof(struct phonethdr)); skb_push(skb, sizeof(struct phonethdr));

View file

@ -113,6 +113,8 @@ void pn_sock_unhash(struct sock *sk)
} }
EXPORT_SYMBOL(pn_sock_unhash); EXPORT_SYMBOL(pn_sock_unhash);
static DEFINE_MUTEX(port_mutex);
static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len) static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
@ -140,9 +142,11 @@ static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len)
err = -EINVAL; /* attempt to rebind */ err = -EINVAL; /* attempt to rebind */
goto out; goto out;
} }
WARN_ON(sk_hashed(sk));
mutex_lock(&port_mutex);
err = sk->sk_prot->get_port(sk, pn_port(handle)); err = sk->sk_prot->get_port(sk, pn_port(handle));
if (err) if (err)
goto out; goto out_port;
/* get_port() sets the port, bind() sets the address if applicable */ /* get_port() sets the port, bind() sets the address if applicable */
pn->sobject = pn_object(saddr, pn_port(pn->sobject)); pn->sobject = pn_object(saddr, pn_port(pn->sobject));
@ -150,6 +154,8 @@ static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len)
/* Enable RX on the socket */ /* Enable RX on the socket */
sk->sk_prot->hash(sk); sk->sk_prot->hash(sk);
out_port:
mutex_unlock(&port_mutex);
out: out:
release_sock(sk); release_sock(sk);
return err; return err;
@ -357,8 +363,6 @@ const struct proto_ops phonet_stream_ops = {
}; };
EXPORT_SYMBOL(phonet_stream_ops); EXPORT_SYMBOL(phonet_stream_ops);
static DEFINE_MUTEX(port_mutex);
/* allocate port for a socket */ /* allocate port for a socket */
int pn_sock_get_port(struct sock *sk, unsigned short sport) int pn_sock_get_port(struct sock *sk, unsigned short sport)
{ {
@ -370,9 +374,7 @@ int pn_sock_get_port(struct sock *sk, unsigned short sport)
memset(&try_sa, 0, sizeof(struct sockaddr_pn)); memset(&try_sa, 0, sizeof(struct sockaddr_pn));
try_sa.spn_family = AF_PHONET; try_sa.spn_family = AF_PHONET;
WARN_ON(!mutex_is_locked(&port_mutex));
mutex_lock(&port_mutex);
if (!sport) { if (!sport) {
/* search free port */ /* search free port */
int port, pmin, pmax; int port, pmin, pmax;
@ -401,8 +403,6 @@ int pn_sock_get_port(struct sock *sk, unsigned short sport)
else else
sock_put(tmpsk); sock_put(tmpsk);
} }
mutex_unlock(&port_mutex);
/* the port must be in use already */ /* the port must be in use already */
return -EADDRINUSE; return -EADDRINUSE;

View file

@ -26,11 +26,11 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
wdev->wext.connect.ie = wdev->wext.ie; wdev->wext.connect.ie = wdev->wext.ie;
wdev->wext.connect.ie_len = wdev->wext.ie_len; wdev->wext.connect.ie_len = wdev->wext.ie_len;
wdev->wext.connect.privacy = wdev->wext.default_key != -1;
if (wdev->wext.keys) { if (wdev->wext.keys) {
wdev->wext.keys->def = wdev->wext.default_key; wdev->wext.keys->def = wdev->wext.default_key;
wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key; wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key;
wdev->wext.connect.privacy = true;
} }
if (!wdev->wext.connect.ssid_len) if (!wdev->wext.connect.ssid_len)