DEBUGMSG("Cleared all message objects on chip\n");
- for (i=1; i<=15; i++) {
+ for (i=0; i<chip->max_objects; i++) {
obj=chip->msgobj[i];
canobj_write_reg(chip,obj,(INTPD_RES|RXIE_RES|TXIE_RES|MVAL_RES),iMSGCTL0);
canobj_write_reg(chip,obj,(NEWD_RES|MLST_RES|TXRQ_RES|RMPD_RES), iMSGCTL1);
}
-void i82527_irq_sync_activities(struct canchip_t *chip, struct msgobj_t *obj)
+int i82527_irq_sync_activities(struct canchip_t *chip, struct msgobj_t *obj)
{
+ int job_done=0;
+
while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)) {
if(can_msgobj_test_and_clear_fl(obj,TX_REQUEST)) {
}
}
+ job_done=1;
+
mb();
can_msgobj_clear_fl(obj,TX_LOCK);
continue;
break;
}
+
+ return job_done;
}
int i82527_irq_handler(int irq, struct canchip_t *chip)
unsigned char msgcfg;
unsigned irq_register;
+ unsigned status_register;
unsigned object;
struct msgobj_t *obj;
int loop_cnt=CHIP_MAX_IRQLOOP;
DEBUGMSG("i82527: iIRQ 0x%02x\n",irq_register);
if (irq_register == 0x01) {
- DEBUGMSG("Status register: 0x%x\n",can_read_reg(chip, iSTAT));
+ status_register=can_read_reg(chip, iSTAT);
+ CANMSG("Status register: 0x%x\n",status_register);
continue;
/*return CANCHIP_IRQ_NONE;*/
}
if (irq_register == 0x02)
object = 14;
- else if(irq_register < 14)
+ else if(irq_register <= 13+3)
object = irq_register-3;
else
return CANCHIP_IRQ_NONE;
can_msgobj_set_fl(obj,TX_REQUEST);
/* calls i82527_irq_write_handler synchronized with other invocations */
- i82527_irq_sync_activities(chip, obj);
+ if(i82527_irq_sync_activities(chip, obj)<=0){
+ /* The interrupt has to be cleared anyway */
+ canobj_write_reg(chip,obj,(MVAL_UNC|TXIE_UNC|RXIE_UNC|INTPD_RES),iMSGCTL0);
+
+ /*
+ * Rerun for case, that parallel activity on SMP or fully-preemptive
+ * kernel result in preparation and finished sending of message
+ * between above if and canobj_write_reg.
+ */
+ i82527_irq_sync_activities(chip, obj);
+ }
}
else {